IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Arduino Discussion :

millis() ne change pas


Sujet :

Arduino

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    retraité
    Inscrit en
    Octobre 2013
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Saône (Franche Comté)

    Informations professionnelles :
    Activité : retraité

    Informations forums :
    Inscription : Octobre 2013
    Messages : 11
    Par défaut millis() ne change pas
    Bonjour
    Je veux étalonner la vitesse d'un moteur en fonction de la largeur d'impulsion d'un port Arduino. J'ai écrit un script qui compte le temps entre 10 tours du moteur (il y a un capteur ). J'utilise 2 variables, 'départ' et 'arrivee', qui lisent millis(). Or, bien qu'il s'écoule plusieurs secondes à vitesse lente pour ces 10 tours, depart et arrivee contiennent la même valeur. Voyez-vous où je me suis trompé ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    int pinVitesse = 6;   
    int pinHall = 2;// le capteur de tours
    int alpha;
    unsigned long arrivee; 
    int n;
     
    unsigned long depart;
     byte compte=0;
    byte valid;
    unsigned long delai;
     
    void setup() {
      pinMode(pinVitesse,OUTPUT);
      pinMode(pinHall, INPUT_PULLUP);
      analogWrite(pinVitesse, 0); 
      Serial.begin(9600);
      Serial.println("depart");
      delay(5000);
    }
     
    void loop() {
      for (n=2;n<16;n++){ 
        if(n<15){alpha=n*16;} else {alpha=255;}// alpha prendra les valeurs 32, 48,...255 
        analogWrite(pinVitesse, alpha); //lance le moteur
        Serial.print("alpha : ");
        Serial.println(alpha);   
        delay(5000); //délai de stabilisationde la vitesse
        valid=1; //autorisela lecture des impulsions Hall
     
        while(compte<=10){
          while(digitalRead(pinHall)!=HIGH){// attente d'une impulsion signalant un tour effectué
            //delay(1);
          } 
           if (valid==1){//première impulsion Hall : démarrage du décompte des tours
              depart=millis();
              Serial.println(depart,DEC);
              compte=0;
              valid=0;
           }
           else{
              compte++; // impulsions suivantes
           }  
        }
       arrivee=millis();// on a effectué 10 tours, on relève millis()
       Serial.println(compte);
       Serial.println(arrivee,DEC);
       analogWrite(pinVitesse, 0); 
        delai=arrivee - depart;// le temps passé pour 10 tours
       Serial.print(", 10 tours en  ");
       Serial.print(delai, DEC);
       Serial.println(" ms");
       delay(5000);
       valid=1;  // nouveau cycle avec le alpha suivant  
       compte=0;
      }
    }
    Extrait du moniteur :
    19:51:29.372 -> alpha : 80
    19:51:34.372 -> 40002
    19:51:34.372 -> 11
    19:51:34.372 -> 40003
    19:51:34.425 -> , 10 tours en 1 ms

  2. #2
    Membre Expert
    Avatar de jpbbricole
    Homme Profil pro
    Retraité des réseaux informatiques
    Inscrit en
    Février 2013
    Messages
    1 017
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Retraité des réseaux informatiques
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Février 2013
    Messages : 1 017
    Par défaut
    Bonsoir aschepens

    Pourquoi n'avoir pas persisté dans l'usage de l'interruption, ça simplifie nettement le comptage des impulsions et, de par là, leur chronométrage.

    Cordialement
    jpbbricole

  3. #3
    Membre averti
    Homme Profil pro
    retraité
    Inscrit en
    Octobre 2013
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Saône (Franche Comté)

    Informations professionnelles :
    Activité : retraité

    Informations forums :
    Inscription : Octobre 2013
    Messages : 11
    Par défaut
    Bonsoir Jpbbricole
    Merci pour votre réponse. En fait, en utilisant une interruption sur le pinHall, j'obtenais le même problème et j'ai pensé essayer autre chose.
    Je ne comprends vraiment pas ce comportement : c'est une façon de faire très classique et il me semble que mon script consulte millis() à des moment très différents.

  4. #4
    Membre Expert

    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2013
    Messages
    1 631
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2013
    Messages : 1 631
    Par défaut Trop vite
    Bonjour,

    Il y a 2 setup et 2 loop.

    Il faut attendre que Hall soit retombé avant de relancer la boucle. Sinon le délai mesuré est celui de la durée de l'état 1 du Hall (arrondi à la ms).
    Par ailleurs on peut se passer de valide en utilisant compte = -1 avant le comptage effectif.

    Par exemple (non testé) :
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
       compte = -1;
       while(compte <= 10){
          while(!digitalRead(pinHall));              // attendre impulsion signalant tour effectué
          if(compte < 0) {                           // 1e impulsion : démarrage du décompte des tours
             depart = millis();
             Serial.println(depart,DEC);
          }
          compte++;
          while(digitalRead(pinHall));               // Attendre fin de l'impulsion
       }
    Salutations

  5. #5
    Membre Expert
    Avatar de jpbbricole
    Homme Profil pro
    Retraité des réseaux informatiques
    Inscrit en
    Février 2013
    Messages
    1 017
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Retraité des réseaux informatiques
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Février 2013
    Messages : 1 017
    Par défaut
    Bonjour aschepens
    Citation Envoyé par aschepens Voir le message
    Bonsoir Jpbbricole
    Merci pour votre réponse. En fait, en utilisant une interruption sur le pinHall, j'obtenais le même problème et j'ai pensé essayer autre chose.
    Je pense que l'usage de l'interruption rend les choses plus faciles, voici ma façon de voire la chose:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    const int pinHall = 2;
     
     
    int toursNombre = 10;
    volatile int toursComptage = 0;
     
    unsigned long toursNombreMillis = 0;
    unsigned long toursNombreDuree = 0;
     
     
    void setup() 
    {
    	pinMode(pinHall, INPUT_PULLUP);
     
    	Serial.begin(9600);
    	attachInterrupt(digitalPinToInterrupt(pinHall), interruptToursComptage, RISING);
     
    	Serial.println("depart");
    }
     
    void loop() 
    {
    	if (toursComptage == 1 && toursNombreMillis == 0)     // Si chrono à l'arrêt redémarrage d'une nouvelle séquence.
    	{
    		toursNombreMillis = millis();
    	}
     
    	if (toursComptage >= toursNombre)     // Si nombre de tours de mesure faits
    	{
    		toursNombreDuree = millis()-toursNombreMillis;
    		Serial.print("Duree pour " + String(toursNombre) + " tours = ");
    		Serial.println(String(toursNombre) + " = " + String(toursNombreDuree) + " millisecondes");
     
    		toursComptage = 0;
    		toursNombreMillis = 0;
    	}
     
    }
     
    void interruptToursComptage()
    {
    	toursComptage ++;
    }
    Cordialement
    jpbbricole

  6. #6
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 907
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 907
    Par défaut
    Salut

    il faut toujours mettre une section critique (bloquer les interruptions, faire une copie des variables sur lesquelles on fait un calcul par exemple puis réactiver les interruptions) quand on travaille sur des variables partagées avec une ISR (sauf si on est capable de garantir l'atomicité d'une opération ce qui est rarement le cas).


    Attention aussi aux test par égalité
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     if (toursComptage == toursNombre)
    si vous n'avez pas de bol il y aura eu deux interruptions pendant que la boucle faisait autre chose et vous aurez dépassé toursNombre, l'égalité ne sera donc plus jamais vérifiée (enfin il faudra attendre que le int revienne à zéro et recommence)
    ==> il vaut mieux tester une inégalité

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     if (toursComptage >= toursNombre)

  7. #7
    Membre Expert
    Avatar de jpbbricole
    Homme Profil pro
    Retraité des réseaux informatiques
    Inscrit en
    Février 2013
    Messages
    1 017
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Retraité des réseaux informatiques
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Février 2013
    Messages : 1 017
    Par défaut
    Bonjour Jay M
    Citation Envoyé par Jay M Voir le message
    Salut

    ==> il vaut mieux tester une inégalité
    J'y avais pensé mais oublié! c'est corrigé.

    Cordialement
    jpbbricole

Discussions similaires

  1. Réponses: 13
    Dernier message: 27/06/2006, 11h20
  2. Réponses: 4
    Dernier message: 04/06/2006, 14h35
  3. [WinCE/PDA] Pourquoi touche TAB ne change pas le focus ?
    Par zitoun dans le forum Windows Mobile
    Réponses: 7
    Dernier message: 24/04/2006, 09h26
  4. [POO] La valeur de l'attribut ne change pas...
    Par slydemusli dans le forum Langage
    Réponses: 3
    Dernier message: 26/03/2006, 12h10
  5. Frames : adresse ne change pas
    Par polo-j dans le forum Balisage (X)HTML et validation W3C
    Réponses: 6
    Dernier message: 14/02/2005, 16h56

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo