asservissement de position

Oui désolé :

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

const int Voie_0=0;
int mesure_brute; // 
int consigne;
int angle; 


void setup()
{
    pinMode(M1, OUTPUT);  
    pinMode(I1, INPUT); 
    pinMode(I2, INPUT); 
    Serial.begin(115200);
   
    mesure_brute=analogRead(Voie_0); // info de l'accéléromètre // lecture position initiale
    angle=-0.651*mesure_brute+329;
    consigne=angle;
    //Serial.println(angle); // afficher à la ligne l'angle
     //delay(1000); 
    
    
    
} // fin du setup



void loop()
{
 

  int value1 = digitalRead(I1); 
  int value2 = digitalRead(I2);
  mesure_brute=analogRead(Voie_0); // position actuelle
  angle=-0.651*mesure_brute+329; // calcul angle actuel
  Serial.println(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+5)
 {
   digitalWrite(M1, HIGH);
   Serial.println("HIGH");
 }
 if (angle<consigne-5) 
 {
   digitalWrite(M1, LOW);
   Serial.println("LOW");
  }
 if (angle >= consigne-5 && angle <= consigne+5)
  {
  Serial.println("ARRET"); 
  analogWrite(E1,0);  // celui-ci est dans le loop et dans le if
  }
      }
 analogWrite(E1,70); // et celui-ci est uniquement dans le loop
  
delay(20);
  }

J'ai mis un petit "celui-ci..." à côté de ce qui me pose problème. Je voulais savoir si mettre 2 vitesses différentes dans un même loop pouvait poser problème ?

Si tu parles d'un problème de fonctionnement ... Oui comme ça, ça ne va pas marcher ...

Conseil: essaie de bien aligner les accolades ... (Il y a une fonction de formatage du programme dans l'IDE (rassures toi, ça ne l'efface pas ...) ... Ca permet d'avoir de des pseudo paragraphes qui aident à la lecture ...

Et maintenant regarde ce que ton programme fait quand tu entres dans la condition if (angle >... && angle <...)
Tu arrêtes ton moteur ... On est d'accord

Mais ensuite ton programme poursuit avec ... ?

PS tu as un delay(1000) et un delay(20) dans le loop ... Un seul suffit, et si ton moteur tourne vite, un délai trop long te feras rater la zone d'arrêt (pendant le delai le micro fait une pause, mais la commande du moteur continue ...) .. C'est à toi de voir pour une pause idéale

Merci ! ça fait beaucoup plus propre, je ne savais pas que cette fonction existait.

Oui le delay(1000) c'est en faisant du copier/coller de ce qui a au-dessus, j'ai oublié de le mettre en commentaire, c'est le delay(20) qui est le bon.
Je vais voir quel delay sera l'idéal alors.

Justement je ne sais pas, vu que c'est une boucle je dirai que, quand mon moteur s'est éteint, si la valeur de angle dépasse la zone >consigne-5 et <consigne+5, il va alors se remettre en marche pour re-rentrer dans l'intervalle voulu et s'arrêter à nouveau, mais à priori ce n'est pas ce qu'il fait avec mon programme là ?

Ben non !

Il n'y a rien à deviner dans un programme ... Il s'exécute, une instruction apres autre

Quand tu sors de la condition d'arrêt ... Le programme passe à quelle ligne ?

N'oublie pas ... La valeur d'angle n'est actualisée qu'au début du loop ... Elle ne changera pas après

Il passe à la suivante alors ?

Dans le if (angle>consigne-5 && angle<consigne+5), il faut peut etre que je mette un while ?

oui il passe à la ligne suivante qui est ... analogWrite(E1,70);
et ça va remettre le moteur en marche ! tu ne verras même pas que ton moteur s'est arreté...

ton programme est vraiment simple ... il n'y a pas 36 choses à faire :

  • mesurer l'angle
  • 2 vérifications pour gérer le réglage
  • 3 vérifications pour gérer le fonctionnement
loop 
mesurer angle

si bouton1 {
    activer sens 1
    tourner 
    consigne = angle
} 
sinon si bouton2 {
    activer sens 1
    tourner 
    consigne = angle
} 
sinon si ange < consigne -5 {
    activer sens1
    tourner
} 
sinon si angle > consigne +5 {
    activer sens2
    tourner
}
sinon si angle >= consigne -5 et angle <= consigne+5 {
    ne pas tourner
}
petite pause
//fin du loop !

ça commence à être un peu plus clair la ??
tu as le matériel sous la main pour tester les choses ???

Si j'ai bien compris, on peut traduire ce que tu veux en pseudo-code :

SI (l'angle est proche de la consigne)
  {
  ne rien faire
  }
SINON
  {
  écrire le bon angle
  }

SINON c'est la commande ELSE

oui je ne vais pas vous écrire le code non plus ... sinon vous n'apprendrez rien

Il faudrait alors que je mette analogWrite(E1,70); avant le if où je demande au moteur de s'arrêter s'il est dans l'intervalle voulu ?

tu mets analogWrite(E1,70); dans chaque condition qui fait tourner le moteur ...

Oui ca marche ! Moi j'étais entrain d'essayer de rajouter des else...

Voici le programme :

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

const int Voie_0 = 0;
int mesure_brute; // Enlever =0 ?????
int consigne;
int angle;


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

  mesure_brute = analogRead(Voie_0); // info de l'accéléromètre // lecture position initiale
  angle = -0.72 * mesure_brute + 368;
  consigne = angle;
  //Serial.println(angle); // afficher à la ligne l'angle
  //delay(1000);



} // fin du setup



void loop()
{


  int value1 = digitalRead(I1);
  int value2 = digitalRead(I2);
  mesure_brute = analogRead(Voie_0); // position actuelle
  angle = -0.72 * mesure_brute + 368; // calcul angle actuel
  Serial.println(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 + 5)
    {
      digitalWrite(M1, HIGH);
      Serial.println("HIGH");
      analogWrite(E1, 70);
    }
    if (angle < consigne - 5)
    {
      digitalWrite(M1, LOW);
      Serial.println("LOW");
      analogWrite(E1, 70);
    }
    if (angle >= consigne - 5 && angle <= consigne + 5)
    {
      Serial.println("ARRET");
      analogWrite(E1, 0);

    }


  }


  delay(20);
}

Il y a juste un petit soucis, quand mon moteur est arrêté parce que la valeur de l'angle est dans l'intervalle voulu, je n'arrive pas le faire touner à l'aide de l'inverseur, saurais-tu comment remédier à cela ?

c'est pourtant simple !

ton moteur est dans l'intervalle ... il s'arrete : ok
tu actionnes ton inverseur ... mais à aucun moment tu ne dis au moteur de repartir ...

il manque des analogWrite(E1, 70); dans les if de l'inverseur ! je te l'avais déjà indiqué ce matin il me semble ....

loop
mesurer angle

si bouton1 {
    activer sens 1
    tourner            <<<<<<<<<<<<< il y a écrit quoi ici ?
    consigne = angle
}
sinon si bouton2 {
    activer sens 1
    tourner            <<<<<<<<<<<<< il y a écrit quoi ici ?
    consigne = angle
}
sinon si ange < consigne -5 {
    activer sens1
    tourner
}
sinon si angle > consigne +5 {
    activer sens2
    tourner
}
sinon si angle >= consigne -5 et angle <= consigne+5 {
    ne pas tourner
}
petite pause
//fin du loop !

Moi je crois que j'ai pas forcément bien compris le besoin au départ :confused:

UniseV, le besoin de départ c'est de demander un angle qui ferra office de consigne, et de le conserver quelque soit les "perturbations". C'est un asservissement de position. C'est dommage que je ne peux pas publier de vidéo, j'aurai pu te montrer le résultat "final" (ou presque) afin que tout le monde puisse parfaitement comprendre.

B83s, je te remercie, le programme fonctionne enfin comme je le souhaite pour le moment !
Je suis désolé d'avoir posé des questions bêtes, mais comme tu as pu le remarquer, je suis vraiment novice en programmation, je partais avec aucune base. Encore merci !

J'ai juste une dernière question, c'est surtout pour ma culture personnelle : sais-tu comment fonctionne le système de vitesse du moteur dans le programme ? Car je peux le faire varier de 0 à 255, donc ça doit être codé sur 8 bits en base 2 je pense ? Et par exemple, quand je dis analogWrite(E1, 70), le "70" comment est-il interprété par la carte ? (70 équivaut à 1000110 en base 2 je crois)

Ouf on y arrive !

Il faut que tu te renseignes sur le PWM (Pulse Width Modulation) ou MLI ( in franchement) pour avoir ta réponse

En arduino 0% c'est 0 et 100% c'est 255... Comme tu l'avais compris, c'est codé sur 8 bits en arduino ...
avec 70 tu es en gros à 35% de la puissance max

Oui j'ai mis du temps… Mais le résultat est là !

D'accord, le lien que tu m'as envoyé est très clair.

Pour le moment je n'ai plus de questions, tu m'as très bien guidé et fait part de ton savoir. Si jamais j'ai encore une petite question pour laquelle je ne trouve pas de réponse, je reviendrai vers toi.

Merci encore pour ton aide ( et ta technique d'aide très instructive ) !

Bonjour,

Je reviens juste ici pour une toute petite explication : sur le lien que tu m'as envoyé, il y a une série de graphe, avec toujours sur l'axe des ordonnées une tension de 5V. Je voudrais savoir, moi qui alimente mon moteur par une petite batterie 12V, si dans ce cas, je remplace 5V par 12V dans le graphique, ou alors si le 5V je dois le garder, auquel cas, a quoi correspond il ?

Merci d'avance

Les graphes sont en 5v car l'arduino ne peut sortir que 5v sur ses broches ... Et encore pas pour alimenter directement un moteur...

Si tu utilises un shield moteur ou un montage perso avec mosfet ou transistor ... Le signal arduino en 5v est la commande qui sert à piloter ton monteur en 12v ...

En gros, quand ta carte arduino envoie 5v, le shield envoie 12v au moteur et 0v sinon ....

D'accord merci beaucoup, c'est exactement ce que je voulais savoir. Merci !