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 :

Code pour mettre en pause un timer et le reprendre


Sujet :

Arduino

  1. #1
    Membre à l'essai
    Inscrit en
    Février 2005
    Messages
    23
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 23
    Points : 11
    Points
    11
    Par défaut Code pour mettre en pause un timer et le reprendre
    Bonjour à tous,
    Je suis débutant en programmation et cherche un code pour pouvoir mettre en place un système de pause (sans utiliser delay), voici ou j'en suis mais je n'arrive pas à le finaliser:
    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
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
     
     
    const int RELAIS1 = 0; //declaration broche 0 output
    boolean etatRelais1 = 0; // Etat du relais (on / off)
     
    // Numéro de la pin du bouton
    const int pinBtn = 13;
     
    // État d'activation de la tempo
    int tempoActive = 0;
     
    // Temps à l'activation de la tempo
    unsigned long tempoDepart = 0;
     
    // Temps à l'activation de la tempo pause
    unsigned long tempoPause = 0; 
     
    // État d'activation de la tempo Pause
    int tempoPauseActive = 0; 
     
    void setup() {
      pinMode(RELAIS1, OUTPUT); //Configure la broche RELAIS en sortie 
           digitalWrite(RELAIS1,1); // met la broche de commande dans l'état voulu
        pinMode(pinBtn, INPUT);    
    }
     
     
     
    void loop() {
     
        // Si le bouton est enfoncé,
        if ( (digitalRead(pinBtn) == 1) && (tempoActive==0) ) {
     
            // Alors on active la temporisation
            tempoActive = 1;
            tempoDepart = millis();
            digitalWrite(RELAIS1,0); // met la broche de commande dans l'état voulu
     
        }
     
        // Si la temporisation est active,
        if ( (tempoActive) && (tempoPauseActive==0) && ((millis() - tempoDepart + tempoPause) >= 10000 ) ) { {
     
       digitalWrite(RELAIS1,1); // met la broche de commande dans l'état voulu
     
                // Et on désactive la temporisation pour ne pas afficher ce message une seconde fois
                tempoActive = 0;
                tempoPause = 0;
            }
     
        }
     
     
     
            if ( (digitalRead(pinBtn) == 1)&& (tempoPauseActive==0) && (tempoActive) && (millis() - (tempoDepart+200) < 10000) ){
            tempoPause = millis();
            tempoPauseActive = 1;        
       digitalWrite(RELAIS1,1); // met la broche de commande dans l'état voulu
        }
     
            if ( (digitalRead(pinBtn) == 1) && (tempoPauseActive) && (tempoActive) ) {
            tempoPauseActive = 0;        
       digitalWrite(RELAIS1,0); // met la broche de commande dans l'état voulu
        }
     
     
    }
    Qu'en pensez-vous?

  2. #2
    Modérateur

    Homme Profil pro
    Ingénieur électricien
    Inscrit en
    Septembre 2008
    Messages
    1 267
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur électricien

    Informations forums :
    Inscription : Septembre 2008
    Messages : 1 267
    Points : 4 829
    Points
    4 829
    Par défaut
    Bonjour Steph

    Ce que j'en pense, c'est que avec un code mieux indenté et certains commentaires un peu plus explicites, je n'aurais pas mal à la tête.

    Ensuite la gestion du bouton n'est pas suffisante, si tu analyses le nombre de transitions entre état "en pause" et "pas en pause" c'est juste énorme quand le bouton est pressé (état à 1), plusieurs dizaines ou centaines de milliers par seconde L'état qui sera retenu au relâchement du bouton sera juste de la loterie. Si je ne me suis pas trompé dans mon analyse, il y aura un passage en pause et une sortie de pause (oui les deux) par tour de Loop() qui est très rapide vu l’absence de fonction à durée longue.

    Je te conseil d'étudier le chapitre 10 du Manuel de laboratoire Langage C et Arduino et notamment comment détecter de manière unique une pression sur un bouton poussoir de même que la gestion des rebonds.

    Ensuite au lieu d'utiliser de multiple variables d'états, autant partir sur une vraie machine d'états: Automate fini — Wikipédia. Cela évitera entre autre de rentrer et de sortir de pause sur le même appuis du bouton.

    Finalement je trouve étonnant que à la fin de la pause, on n'enregistre pas le temps (pas d'appel à millis();), donc comment faire pour ajouter le temps de la pause à celle de la tempo? Mais cela je n'ai pas investigué en détail. Pas vu également le traitement du cas de plusieurs pauses dans la même tempo.

    Bonne suite

    Delias

  3. #3
    Membre à l'essai
    Inscrit en
    Février 2005
    Messages
    23
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 23
    Points : 11
    Points
    11
    Par défaut
    Merci Delias pour ton retour,
    J'ai introduis un delay(100) qui m'a permis d'avancer au niveau des if:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
        if ( (digitalRead(pinBtn) == 1) && (tempoActive==0)) {
                delay(100);
        while(digitalRead(pinBtn) == 1); 
        delay(100);
            tempoActive = 1;
            tempoDepart = millis();
            digitalWrite(RELAIS1,0); // met la broche de commande dans l'état voulu
        }

  4. #4
    Membre à l'essai
    Inscrit en
    Février 2005
    Messages
    23
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 23
    Points : 11
    Points
    11
    Par défaut
    Voici le code fonctionnel:
    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
     
    const int RELAIS1 = 0; //declaration broche 0 output
    boolean etatRelais1 = 0; // Etat du relais (on / off)
    const int pinBtn = 13; // Numéro de la pin du bouton
    int tempoActive = 0; // État d'activation de la tempo
    unsigned long tempoDepart = 0; // Temps à l'activation de la tempo
    unsigned long tempoPause = 0; // Temps à l'activation de la tempo pause
    int tempoPauseActive = 0; // État d'activation de la tempo Pause
     
    void setup() {
      pinMode(RELAIS1, OUTPUT); //Configure la broche RELAIS en sortie 
           digitalWrite(RELAIS1,1); // met la broche de commande dans l'état voulu
    }
     
     
     
    void loop() {   
        if ( (digitalRead(pinBtn) == 1) && (tempoActive==0) && (tempoPauseActive == 0)) { // Si le bouton est enfoncé,
                delay(100);
                while(digitalRead(pinBtn) == 1); 
                delay(100);
                        tempoActive = 1;
                        tempoDepart = millis();
                        digitalWrite(RELAIS1,0);
        }
     
         else if (  (digitalRead(pinBtn) == 1) && (tempoPauseActive==0) && (tempoActive) ){//démarrage potentiel de la pause
                delay(100);
                while(digitalRead(pinBtn) == 1); 
                delay(100);
                        tempoPause = millis();
                        tempoPauseActive = 1;        
                        digitalWrite(RELAIS1,1);
        }
     
         else if (  (digitalRead(pinBtn) == 1) && (tempoPauseActive) && (tempoActive) ) {//finalisation du démarrage de la pause
                delay(100);
                while(digitalRead(pinBtn) == 1); 
                delay(100);
                        tempoPause = millis()-tempoPause;
                        tempoPauseActive = 0;        
                        digitalWrite(RELAIS1,0); 
        }
     
     
        if ( (tempoActive) && (tempoPauseActive==0) && ((millis() - (tempoDepart)) >= (10000  + tempoPause)) ) { // Si la temporisation est active,
                digitalWrite(RELAIS1,1); 
                tempoActive = 0;
                tempoPause = 0;
                tempoDepart = 0;
                tempoPauseActive = 0; 
        }
    }
    Encore merci pour tes pistes Delias, je découvre Arduino (UNO) Pensez-vous que ce code puisse être optimisé? il n'y a pas de librairie pour cette fonction?

  5. #5
    Modérateur

    Homme Profil pro
    Ingénieur électricien
    Inscrit en
    Septembre 2008
    Messages
    1 267
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur électricien

    Informations forums :
    Inscription : Septembre 2008
    Messages : 1 267
    Points : 4 829
    Points
    4 829
    Par défaut
    Bonsoir Steph

    Ton code est empirique et cela se voit.
    Tu as résolu ton problème de détection d'appuis sur le bouton, mais tu utilises delay(); ce que tu ne voulais pas au début, et de même tu as des while(digitalRead(pinBtn) == 1); bloquant tant que le bouton est pressé, c'est généralement considéré de la même manière que le delay();. Pour moi cette partie ce n'est pas de la bonne programmation. Revois le chapitre du cours d'Arduino que j'ai indiqué dans mon précédent message.

    Pour éviter d'écrire la routine de gestion du bouton à plusieurs reprises, tu devrais analyser l'état du bouton au début de la loop, puis stocker son état pour les tests qui viennent en suite. Ensuite il faut bien enchainer les tests, pour que un seul soit activé par tour de loop. Cela implique généralement d'utiliser une structure de if, else if, else if, etc... ou une machine d'état comme je le détaille un peu plus loin.

    Pour aller un peu plus loin, l'état du bouton c'est par exemple un enum de 4 états: Low, Rise, Up, Fall. Rise et Fall c'est quand le bouton vient de changer d'état, ce n'est valable que pour un tour de loop. Low et Up c'est des états permanent dans le cas contraire. Le traitement de l'anti-rebond est également réalisable par mémorisation de la valeur de millis();.

    Et je réitère mon commentaire sur l'usage d'une petite machine d'état dans le cas de ce programme. Cela se traduirait par une suppression des variables tempoActive et tempoPauseActive et par la création d'une seule variable d'état pouvant valoir ici 3 valeurs: Off, Tempo, Pause (donc un enum est à nouveau le bienvenu). Le loop se composerait dès lors de la routine d'analyse du bouton, puis d'un switch case et dans les case des tests pour gérer les transitions d'état.

    Un commentaire additionnel pour ces variables tempoActive et tempoPauseActive, tu utilises des variables de type int pour stocker de simple booléen. Avec un micro à 8 bits comme celui de l'Arduino cela multiplie par 2 le temps de traitement de ces variables. Dans ce cas il faut utiliser le type bool, ou un entier de 8 bits: char (signé) ou byte (non signé).

    Et finalement il me semble que le programme ne prend pas en compte de multiples pauses, je ne sais pas si c'est voulu ainsi ou pas.

    Bonne suite

    Delias

Discussions similaires

  1. [E-03] code pour mettre en forme un email ?
    Par Emily2711 dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 26/02/2009, 11h51
  2. Mettre du code pour mettre à jour une zone
    Par AgriPhilou dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 01/06/2008, 13h25
  3. Changer le code pour mettre plutôt une image ?
    Par Bruno13 dans le forum Delphi
    Réponses: 1
    Dernier message: 17/11/2006, 18h09
  4. [FTP] Code pour mettre une image en background
    Par Link14 dans le forum Langage
    Réponses: 2
    Dernier message: 24/02/2006, 21h10
  5. Mettre en pause le Timer !
    Par NaDiA_SoFt dans le forum C++Builder
    Réponses: 14
    Dernier message: 12/09/2003, 21h32

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