[RESOLU] Continuer un programme pendant un chronomètre

Bonjour,
Alors voilà, je suis un élève de 1ère et ai pour projet scolaire de faire une main robotisée où plutôt "piloter" une pince en contractant ou non le bras. J'ai donc utilisé un EMG Sensor (http://wiki.seeed.cc/Grove-EMG_Detector/) branché sur ma carte Arduino UNO lié à un servomoteur quelconque. Le sensor émettant des données très peu variantes qu'on contracte ou non, j'ai donc premièrement fait une moyenne de ses valeurs pour ensuite faire la moyenne de leurs écart (plus gros écart de valeur lorsqu'on contracte la bras, probablement du aux tremblements du bras lorsqu'il est constamment contracté) afin de pouvoir convenablement les utiliser. Ainsi lorsque la moyenne de l'écart est supérieure à une certaine valeur, la pince se referme à part si elle est déjà en mouvement (!=position fermée && position ouverte) où elle attend que le précédent mouvement se termine avant d'effectuer de le prochain [Même processus lorsqu'on veut ouvrir la main]. J'ai donc du créé une valeur "statut" qui lorsqu'elle est égale à -1 signifie que la pince n'est pas en mouvement, lorsqu'elle est égale à 0 la pince est en cour d'ouverture, lorsqu'elle est égale à 1 elle est en cours de fermeture. La valeur passe donc à 1 lorsqu'on veut fermer la main puis repasse à -1 lorsque la main est fermée, et passe à 0 lorsqu'on veut l'ouvrir puis repasse à -1 lorsqu'elle est ouverte (la pince met 1750ms à s'ouvrir et la même durée pour se fermer). Je veut donc que lorsque le statut passe à 0 ou 1, un chronomètre de 1750ms se lance, lorsqu'il est terminé, statut repasse à -1 mais pendant ce chronomètre, le programme doit toujours avancer or je ne sais pas comment faire (j'avais premièrement mit un delai de 1750ms, le programme ne continue donc pas d'avancer. Puis j'ai vu qu'on pouvait utiliser millis() or je ne sais pas comment faire).

Voici mon code :

#include <Servo.h>
Servo servo;

void setup(){                                     //Init. du graphique, du servomoteur et de son statut (-1, c'est-à-dire moteur non utilisé).
  Serial.begin(115200);
  
  servo.attach(1);
  servo.writeMicroseconds(1850);
  delay(2000);
  servo.writeMicroseconds(600); 
  delay(2000);
  
  int statut = -1;
}

Serial.println("Main prête à l'emploi.");




void loop(){                                        //Création d'une boucle qui répetera le programme continuellement.
  long somme=0;                                     //Init. des valeurs qui vont être utilisées.
  int moyS=0;
  int mini=1000;
  int maxi=0;
  double ecart=0;
  double moyE=0;


 for(int i=1; i<=100; i++){                         //Création d'une boucle qui va se répeter 100 fois.
    for(int j=1; j<=10; j++){                       //Création d'une boucle qui va se répeter 20 fois. [Les 2 
                                                                boucles permettent d'exploiter le signal émit par le capteur 
                                                                en faisant 
      somme+=analogRead(A2);                   //Lecture des valeurs du capteur.  une 
                                                                moyenne car il est très difficile de les exploiter sans 
                                                                changements]
    }

    moyS=somme/10;                                 //Moyenne des 10 valeurs issues du capteur.
    somme=0;

    if(moyS<mini){                                     //Définition d'un minimum et d'un maximum.
      mini=moyS;
    }

    if(moyS>maxi){
      maxi=moyS;
    }

    ecart=maxi-mini;                                   //Calcul de l'écart
    ecart+=ecart;
  }
  moyE=ecart/100;                                    //Moyenne de l'écart
  


  ecart=0;                                                 //Remise des valeurs à leur initial
  mini=1000;
  maxi=0;
  moyS=0;  
  


  if(moyE>=0.85){                                    //Si on ferme la main
    if(servo.read()==600){                         //Et que le servo est sur la position "ouvert": la fermer
      servo.writeMicroseconds(1850);  
      statut = 1;
      
      //delay(1750);
      //statut = -1;
    }

    else if(servo.read()!= 1850){
      if(statut == 1){
        delay = (1850-servo.read())*1.4;
        delay(delay+5);
        servo.writeMicroseconds(1850);
       
        //delay(1750);
        //statut = -1;
      }
      
      if(statut == 0){
        delay = (servo.read()-600)*1.4;
        delay(delay+5);
        servo.writeMicroseconds(1850);
        
        //delay(1750);
        //statut = -1;
      }
    }
  }



  else{
    if(servo.read()==1850){
      servo.writeMicroseconds(600);
      statut = 0;
      
      //delay(1750);
      //statut = -1;
    }

    else if(servo.read()!= 1850){
      if(statut == 1){
        delay = (1850-servo.read())*1.4;
        delay(delay+5);
        servo.writeMicroseconds(600);
        
        //delay(1750);
        //statut = -1;
      }
      
      if(statut == 0){
        delay = (servo.read()-600)*1.4;
        delay(delay+5);
        servo.writeMicroseconds(600);
        
        //delay(1750);
        //statut = -1;
      }
    }
  }
  moyE=0;
}

En espérant m'être fait comprendre, si ce n'est pas le cas demandez moi de vous ré-expliquer car j'aimerais bien finaliser ce projet.

Bonne journée

Bonjour, bienvenue sur le forum et merci d'avoir utilisé les balises de code et formulé une question construite ! bravo

Puis j'ai vu qu'on pouvait utiliser millis() or je ne sais pas comment faire

lisez le tuto d'eskimon [ Arduino 202] Introduire le temps ou alors en anglais le post épinglé en haut du forum Using millis() for timing. A beginners guide --> ça devrait vous donner le principe général

Ce que vous décrivez - c'est typiquement une définition de programme qui se prête bien à la programmation par machine à états (cf mon tuto éventuellement)

Tu sais quand on fait des paragraphes pas trop long (4 à 5 lignes) et qu'on saute des lignes, le texte est plus facile à lire.

Je te le dis direct : vu ton pavé je n'ai fais aucun effort pour le lire.
C'est mon choix, et je pense que je ne suis pas le seul dans ce cas.

Je recopie un extrait du message épinglé "Bienvenue sur le forum de la communauté francophone" que visiblement tu n'as pas jugé utile de lire.

Règle 5 :
Apprenez à présenter votre texte. Certains messages ne comportent ni paragraphes, ni retours à la ligne. Comme ils sont illisibles, ils sont généralement ignorés.
C'est dur, mais rappelez-vous bien que l'on vous répond sur notre temps de repos, après une journée de travail qui a pu être éprouvante..

Je te rappelle que celui qui a besoin d'aide c'est toi et que c'est nous qui pouvons te l'a donner mais uniquement dans la mesure où on a envie de le faire.
Ta présentation ne donne aucune envie de le faire.
Nous ne sommes pas le service après vente Arduino, nous sommes des bénévoles totalement libres.

vous êtes un peu dur - certes c'est un gros paté de texte, mais au moins c'est construit... on a vu pire !

C'est vrai et c'est pour cela qu'en cette période un peu dure où le pétage de plomb n'est pas loin je pense que je suis resté "modéré" (désolé j'ai fait 68 mais pas de stage au Quai d'Orsay).

Ce qui me gonfle c'est que des personnes interviennent sur un forum sans l'avoir parcouru auparavant pour en comprendre le fonctionnement.

Cela me parait une évidence que chaque forum a ses règles et un mode de fonctionnement particulier et que la moindre des politesses c'est de commencer par se renseigner.
Les messages qu'un modérateur a pris la peine d'épingler sont la première source d'information.

Et puis à partir de la classe de 1ere le monde des adultes n'est pas très loin et il sera implacable, aucune place à la pitié.
Il faut qu'ils apprennent à sortir de l'enfance.

Je vous remercie de votre aide je regarde ça dès que je peux. Désolé pour la clarté du code, c’est le premier projet que je fait mais il est vrai que le code est plus facilement compréhensible par celui qui l’a fait que pour celui qui ne l’a jamais lu, je le modifie donc dès la publication de cette réponse. Merci de me l’avoir signalé parce que c’est vrai que pour des personnes essayant d’en aider de nombreuses autres ça ne doit pas être simple

b1oukoi:
Je vous remercie de votre aide je regarde ça dès que je peux. Désolé pour la clarté du code, c’est le premier projet que je fait mais il est vrai que le code est plus facilement compréhensible par celui qui l’a fait que pour celui qui ne l’a jamais lu, je le modifie donc dès la publication de cette réponse. Merci de me l’avoir signalé parce que c’est vrai que pour des personnes essayant d’en aider de nombreuses autres ça ne doit pas être simple

c'est plus votre demande qu'il faut aérer... par exemple rédigée comme cela, ça aurait été mieux


Bonjour,

Alors voilà, je suis un élève de 1ère et ai pour projet scolaire de faire une main robotisée où plutôt "piloter" une pince en contractant ou non le bras.

J'ai donc utilisé un EMG Sensor branché sur ma carte Arduino UNO lié à un servomoteur quelconque.

Le sensor émettant des données très peu variantes qu'on contracte ou non, j'ai donc premièrement fait une moyenne de ses valeurs pour ensuite faire la moyenne de leurs écart (plus gros écart de valeur lorsqu'on contracte la bras, probablement du aux tremblements du bras lorsqu'il est constamment contracté) afin de pouvoir convenablement les utiliser.

Ainsi lorsque la moyenne de l'écart est supérieure à une certaine valeur, la pince se referme — SAUF si elle est déjà en mouvement (!=position fermée && position ouverte) où elle attend que le précédent mouvement se termine avant d'effectuer le prochain mouvement [Même processus lorsqu'on veut ouvrir la main].

J'ai donc créé une valeur "statut" qui :

  • lorsqu'elle est égale à -1 signifie que la pince n'est pas en mouvement,
  • lorsqu'elle est égale à 0 la pince est en cour d'ouverture,
  • lorsqu'elle est égale à 1 elle est en cours de fermeture.

La valeur passe donc à 1 lorsqu'on veut fermer la main puis repasse à -1 lorsque la main est fermée, et passe à 0 lorsqu'on veut l'ouvrir puis repasse à -1 lorsqu'elle est ouverte.

MA QUESTION:

La pince met 1750ms à s'ouvrir et la même durée pour se fermer.

Je souhaite que lorsque le statut passe à 0 ou 1, un chronomètre de 1750ms se lance, lorsqu'il est terminé, statut repasse à -1 mais pendant ce chronomètre, le programme doit toujours avancer or je ne sais pas comment faire

(j'avais premièrement mit un delai de 1750ms, le programme ne continue donc pas d'avancer. Puis j'ai vu qu'on pouvait utiliser millis() or je ne sais pas comment faire).

Merci de me donner des indications sur comment aborder ce sujet.


voilà c'est en gros votre texte, mais un peu plus espacé...

D’accord je fais ça dès que je peux parce qu’avec un téléphone ce n’zst pas simple...

parce qu'avec un téléphone ce n'est pas simple...

Évidement si tu met un handicap :grin:

Mais cela fonctionne dans les deux sens : si tu lis nos réponses sur ton téléphone si c'est aéré et avec le code entre balise tu trouvera aussi que c'est mieux. :grin:

J'ai réussi sans utilisation du millis() puisqu'il n'était en fait pas utile, il fallait juste tester le programme pour trouver la solution. Voici donc le nouveau programme entièrement fini, entièrement fonctionnel et expliqué si ça peut aider quelqu'un. Je met le topic en résolu, merci d'avoir essayé de m'aider :slight_smile:

#include <Servo.h>                                      //Importation de la bibliothèque correspondant aux servomoteurs.
Servo servo;

int somme=0;                                            //Init. des valeurs qui vont être utilisées au cours du programme.
int moyS=0;
int mini=1000;
int maxi=0;
float ecart=0;
float totalE=0;
int etat=-1;
int fixe=0;
int aservo=0;
int bservo=0;
float delai;


void setup(){                                           //Init. du servomoteur et de son état (-1, c'est-à-dire moteur non-utilisé). + [animation qui nous permet de savoir quand la main est prête
  servo.attach(2);                                      //                                                                             à être utilisée].
  servo.write(5);
  delay(2000);
  servo.write(126); 
  delay(2000);
}

void loop(){                                            //Création d'une boucle qui répetera le programme continuellement.
  for(int k=1; k<=8; k++){                                //Création d'une boucle qui va se répeter 8 fois.
    for(int i=1; i<=100; i++){                              //Création d'une boucle qui va se répeter 100 fois.       [Les 3 boucles permettent d'exploiter le signal émit par le capteur en faisant
      for(int j=1; j<=10; j++){                               //Création d'une boucle qui va se répeter 10 fois.      une moyenne car il est très difficile à exploiter sans changements et surtout
        somme+=analogRead(A2);                                  //Lecture des valeurs issues du capteur.              très peu fiable: il faut donc le rendre fiable].
      }

      moyS=somme/10;                                          //Moyenne des 10 valeurs issues du capteur.
      somme=0;

      if(moyS<mini){                                          //Définition d'un minimum.
        mini=moyS;
      }

      if(moyS>maxi){                                          //Définition d'un maximum.
        maxi=moyS;
      }

      ecart=maxi-mini;                                        //Calcul de l'écart à partir du maximum et du minimum.
      ecart+=ecart;                                           //Somme des écarts qui donnet à la fin de la boucle un écart total de 1000 valeurs.
    
    }
 
    totalE+=ecart;                                          //Somme des 8 écarts totaux.
 
    ecart=0;                                                //Remise des valeurs utilisées précédement à leur initial (sauf totalE).
    mini=1000;
    maxi=0;
    moyS=0;
  }
  
  if(totalE/8>=81){                                       //Si on force avec notre bras (si la moyenne des écart totaux est supérieures à 81 [lorsque le bras n'est pas contracté les écarts totaux sont autour de 76]),
    if(servo.read()==5 || aservo==bservo){                  //Et si le servo est sur la position "fermée" ou que aservo est égal à bservo:
      etat=-1;                                                //Définir l'état de la pince sur "fixe".
      fixe=1;
    }
    else if(servo.read()==126){                             //Et si le servo est sur la position "ouvert":
      servo.write(5);                                         //Fermer la pince
      etat=1;                                                 //Et définir l'état de la pince sur "en cours de fermeture".
    }
    else{                                                   //Sinon (si le servo ne remplie la condition 1 et la condition 2),
      if(etat==1 && fixe==0){                                 //Et si l'état du servo est sur "en cours de fermeture":
        aservo=servo.read();                                    //Assigner à aservo et bservo à très proche de 15ms d'intervalle, l'angulation du servo.
        delay(1750/21+0.00001);
        bservo=servo.read();
    
        if(aservo==bservo){                                   //Si les deux valeurs sont égales cela signifie que la pince est bloquée et donc qu'elle rencontre un objet:
          servo.write(aservo);                                  //Arrêter le servomoteur sur sa position
          fixe=1;                                               //Définir fixe sur 1 ce qui équivaut à dire que la pince est bloquée en position de fermeture.
        }
      }
   
      if(etat == 0){                                        //Si la pince est "en cours de fermeture":
        delai = (126-servo.read())*(1750/21);                 //Calcul du délai à attendre avant que la pince termine son mouvement.
        delay(delai);                                         //Mise en place du délai, la pince a donc fini de se fermer.
        etat=-1;                                              //L'état de la pince est désormais sur "moteur non-utilisé".
        servo.write(5);                                       //Fermeture de la pince.
        etat=1;                                               //Définition de l'état sur "en cours de fermeture.
      }
    }
  }
 
  else{                                                 //Si le bras est relaché,
    fixe=0;                                               //Définir fixe sur 0 ce qui équivaut à dire que la pince est désormais débloquée car elle lâche l'objet qu'elle soutenait.
   
    if(servo.read()==126){                                //Et si la pince est ouverte:
      etat=-1;                                              //Définir son état sur -1 car elle est imobile.
    }
    else if(servo.read()==5){                             //Sinon, si elle est fermée:
      servo.write(126);                                     //L'ouvrir.
      etat=0;                                               //Définir son état sur 0 car elle est "en cours d'ouverture".
    }
    else if(etat==1){                                     //Sinon, si son état est sur 1, c'est-à-dire que la pince est en cours d'ouverture:
      delai = (servo.read()-5)*(1750/21);                   //Calcul du délai à attendre avant que la pince termine son mouvement.
      delay(delai);                                         //Mise en place du délai, la pince a donc fini de se fermer.
      etat=-1;                                              //L'état de la pince est désormais sur "moteur non-utilisé".
      servo.write(126);                                     //Ouvrir la pince.
      etat=0;                                               //Définir son état sur "en cours d'ouverture".
    }
  }
  
  totalE=0;                                             //Remise de la valeur totalE à son initial.
}

Bonne soirée