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

C Discussion :

[PIC] Double Fonctionalité d'un bouton poussoir


Sujet :

C

  1. #1
    Membre du Club
    Inscrit en
    Septembre 2008
    Messages
    384
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 384
    Points : 52
    Points
    52
    Par défaut [PIC] Double Fonctionalité d'un bouton poussoir
    Bonjour,

    Je suis bloqué sur une petite fonctionnalité tout simple, que j'essaie de mettre en œuvre :

    J'ai un bouton poussoir qui au repos est au niveau haut, une pression sur celui-ci génère un niveau bas.

    - Je voudrai, que lorsque j'appuie un court instant ( disons 1/2s ) sur celui ci il se produise une action 1.

    - Si l'appuie sur ce bouton plus longuement ( >3s ) alors c'est l'action 2 qui sera exécutée.


    Mon code dispose de moyens pour capturer et mesurer le temps de façon précise ( TICK ) , ce qui me pose pb c'est le codage de la fonctionnalité elle-même.

    J'ai écris ceci, voici le comportement constaté :

    1 court appuie : l'action 1 est executée
    1 long appuie : l'action 1 et l'action 2 sont executés.
    -> mon pb se situe ici justement : je voudrai que ce soit QUE l'action 2 qui soit exécutée.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    TICK T0_Time;
    TICK T1_Time;
    ...

    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
    if (BUTTON1_IO == 0) T0_Time = TickGet();
     
    while(BUTTON1_IO == 0)
    {
     
    if ((TickGet() - T0_Time <= TICK_SECOND/2))
            {
    		// ACTION 1
    		LED1_IO = 1;
    		}
     
    if ((TickGet() - T0_Time >= 3*TICK_SECOND))
    		{
    		// ACTION 2
    		LED2_IO = 1;
    		}
    }

    Peut être faut il partir différemment, capturer le temps T0 dès lors que le BP est appuyé ( génération d'un niveau bas) , attendre son retour au niveau haut : capturer le temps T1
    ->
    si T1 - T0 >= 0.3s --> Action 1
    si T1 - T0 >= 3s --> Action 2

    avec qqchose de ce style :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (TickGetDiff(T1_Time, T0_TIME) >= 3*TICK_SECOND)

    Je n'ai pas réussi à coder cela, car je ne vois pas comment coder l'acquisition de T1 qui correspond au retour du BP au niveau haut

    Pouvez vous m'aider svp ?
    Je vous remercie,

  2. #2
    Membre expérimenté
    Profil pro
    Développeur en systèmes embarqués retraité
    Inscrit en
    Mars 2006
    Messages
    947
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2006
    Messages : 947
    Points : 1 351
    Points
    1 351
    Par défaut
    Salut,

    C'est plus un problème d'algorithme que de C. Le premier problème que je vois, c'est que ta lecture du bouton est bloquante. Disons que c'est assumé.

    Une façon simple de faire est de compter le temps à partir du moment où l'état du bouton bascule (c'est à dire le moment où il passe de repos à appuyé) Si le relâchement intervient avant 3 secondes tu traites le "court". Si la durée passe les 3 secondes tu traites le "long". Le fait de commencer à compter sur un changement d'état repos/appuyé t'affranchit de ton problème de double commande.

    A+

    Pfeuh

  3. #3
    Membre du Club
    Inscrit en
    Septembre 2008
    Messages
    384
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 384
    Points : 52
    Points
    52
    Par défaut
    Je ne vois toujours pas ce que je dois changer dans le code que j'ai écris.

    Logiquement,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (BUTTON1_IO == 0) T0_Time = TickGet();
    capture déja le temps T0 au moment du changement d'etat, ,n'est ce pas ?
    au repos ( sans appuie sur le bouton ) BUTTON1_IO est au niveau 1

    Peux tu me montrer la modif que je dois effectuer ?
    Merci beaucoup,

  4. #4
    Membre confirmé
    Avatar de haraelendil
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2004
    Messages
    283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2004
    Messages : 283
    Points : 533
    Points
    533
    Par défaut
    Le problème vient de ton while.
    Au début tu stocke la valeur de getTick lors du début de l'appuie, mais ton while(BUTTON1_IO == 0) est vrai et donc il passe tout de suite dedans, et forcément allume la LED1 puisque le temps écoulé est très court, puis ensuite, si tu reste appuyé, il allume la deuxième.

    Ce que toi tu veux faire, c'est comparé le moment auquel on appuie sur le bouton (ce que tu as déjà fait), et après le moment auquel il est RELACHE

    un simple point virgule:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    while(BUTTON1_IO == 0);
    et enlève les accolades du while et ça devrait marcher.
    Il bouclera dans le while tant que le bouton est appuyé, et ensuite évaluera le temps écoulé quand il sera relaché.

    (cela dit, attention aux rebonds)

  5. #5
    Membre du Club
    Inscrit en
    Septembre 2008
    Messages
    384
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 384
    Points : 52
    Points
    52
    Par défaut
    Merci de ton aide,

    Peux tu me dire ce que provoque le point virgule en terme de traitement ?

    Comme tu le dit justement, peut on eviter l'interpretation d'evenruels rebonds avec des flags par exemple ?

    Cordialement,

  6. #6
    Membre confirmé
    Avatar de haraelendil
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2004
    Messages
    283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2004
    Messages : 283
    Points : 533
    Points
    533
    Par défaut
    le point virgule fait juste tourner le while sans rien faire
    revient au même que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    while(condition)
    {
    }
    Après pour la gestion des rebonds, il y a plein de solutions, plus ou moins efficaces et évoluées.
    Une toute simple serait de mettre un toute petite tempo avant ton while pour que le signal ait le temps de se stabiliser.
    Sinon tu peux faire ça électroniquement avec un simple passe bas, comme ça ça ne surcharge pas ton programme...
    Après si ça ne te va pas, il existe encore plein d'autres solutions plus poussées

  7. #7
    Membre expérimenté
    Profil pro
    Développeur en systèmes embarqués retraité
    Inscrit en
    Mars 2006
    Messages
    947
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2006
    Messages : 947
    Points : 1 351
    Points
    1 351
    Par défaut
    Bon, faisons simple

    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
    Tant que (bouton relâché)
        ne rien faire
     
    // si on est là c'est que le bouton a basculé
    Initaliser compteur_temps
     
    tant que (compteur_temps < 3 secondes ET bouton enfoncé)
        compter temps
     
    // si on est là c'est que les trois secondes sont passée
    // ou que le bouton est relâché
    si (compteur_temps >= 3 secondes)
       traitement long
    sinon
       traitement court

  8. #8
    Membre du Club
    Inscrit en
    Septembre 2008
    Messages
    384
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 384
    Points : 52
    Points
    52
    Par défaut
    J'ai essayé ceci selon les conseils de haraelendil, mais ça ne fonctionne pas correctement , étrangement, la LED2 s'allume en premier la LED1 suit quelques instant plus tard ...

    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
     
    if (BUTTON1_IO == 0) T0_Time = TickGet();
     
    while(BUTTON1_IO == 0);
     
    if ((TickGet() - T0_Time <= TICK_SECOND/2))
                    {
    		// ACTION 1
    		LED1_IO = 1;
    		}
     
    if ((TickGet() - T0_Time >= 3*TICK_SECOND))
    		{
    		// ACTION 2
    		LED2_IO = 1;
    		}

    pfeuh :
    Mon code est à intégrer dans une boucle infinie, et le process est multitaches, donc si je fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Tant que (bouton relâché)
        ne rien faire
    Je pense que le code va se bloquer et attendre que le bouton soit pressé pour commencer le traitement, c'est un problème car ça va empêcher les autres tâches du programme de s'exécuter malgré tout .

  9. #9
    Membre du Club
    Inscrit en
    Septembre 2008
    Messages
    384
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 384
    Points : 52
    Points
    52
    Par défaut
    Je suis parvenu à mes fins avec ce code, j'imagine qu'il peut sans doute être simplifié ( vos remarques sont les bienvenues )

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    static BYTE old_pos;
    static BYTE new_pos;
    ...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    old_pos = BUTTON1_IO;     // Défini l'état initial : old_pos = BUTTON1_IO
    ...
    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
     
        while(1)
        {
        new_pos = BUTTON1_IO;
    	// Détection d'un changement d'état
    	if (old_pos != new_pos) 
    	{
    	if (new_pos == 1) 
    		{
    		// Traitement du front montant
    		T1_Time = TickGet();
     
    		// Traitement appuie long :
    		if (TickGetDiff(T1_Time, T0_Time) > 2*TICK_SECOND) LED1_IO = 1;
     
    		// Traitement appuie court :
    		if (TickGetDiff(T1_Time, T0_Time) < TICK_SECOND/2) LED2_IO = 1;
     
    		}
    		else 
    		{
    		// Traitement du front descendant
    		T0_Time = TickGet();
    		}
     
          old_pos = new_pos;
          }
    Mon soucis à présent,est la présence de rebonds lorsqu'on appuie sur le bouton poussoir, pouvez vous me dire ce que je dois modifier pour les éviter ?

  10. #10
    Membre expérimenté
    Profil pro
    Développeur en systèmes embarqués retraité
    Inscrit en
    Mars 2006
    Messages
    947
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2006
    Messages : 947
    Points : 1 351
    Points
    1 351
    Par défaut
    Citation Envoyé par lcoulon Voir le message
    le process est multitaches
    Tu parles de vrai multitâches ou de machines d'état? Si c'est du vrai multitâche et qu'une tâche est allouée à la gestion du bouton, ça ne pose pas de problème. si c'est des machines d'état, il suffit d'en écrire une pour la gestion du bouton.

    Pour les rebonds, il faut considerer un temps minimum pour qu'une impulsion ne soit pas considérée comme un rebond. Si la durée de l'appui est inférieure à ce temps, l'info doit être ignorée.

Discussions similaires

  1. Réponses: 3
    Dernier message: 26/11/2010, 16h27
  2. J'ai besoin de bouton poussoir
    Par lgjean dans le forum C++Builder
    Réponses: 3
    Dernier message: 12/10/2006, 10h06
  3. Pb pour double action avec un bouton
    Par Dawax dans le forum Flash
    Réponses: 11
    Dernier message: 02/07/2006, 17h54
  4. double click sur un bouton
    Par gdpasmini dans le forum Windows
    Réponses: 7
    Dernier message: 10/05/2006, 14h38
  5. Source LaTeX : faire un bouton poussoir dans le PDF
    Par pierrot_latex dans le forum Editeurs / Outils
    Réponses: 3
    Dernier message: 24/02/2006, 14h52

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