Le bouton poussoir

Python est le langage de prédilection du Raspberry Pi

Modérateurs : Francois, Manfraid

Bud Spencer
Raspinaute
Messages : 1089
Enregistré le : lun. 15 août 2016 21:38

Re: Le bouton poussoir

Message par Bud Spencer » sam. 1 févr. 2020 12:46

MSG a écrit :
ven. 31 janv. 2020 19:58
@Bud Spencer
L'anti rebond peut être géré de diverse manières .
Vi, je sais bien, mais il ni a pas besoin de tout un patatra avec je ne sais combien de bits et d'évaluations pour exécuter une action au relâchement d'un bouton. En plus de te compliquer la vie pour rien, ta méthode n'est pas fiable dans le sens ou le temps que tu traites tes bits et que tu évalues tout ca pour retourner une valeur qu'il faudra encore évaluer à son retour, il y a de grande chance que le bouton ait de nouveau changé d'état ;)

le petit exemple que j'ais mis décrit simplement le cycle linéaire le plus court a respecter, a savoir :

Pas besoin d'évaluer inutilement un relâchement si il ni a pas eu d'appuis
Protection à l'appuis pour que les rebonds ne soit pas interprétés comme un relâchement
Attente du relâchement
Protection au relâchement pour que les rebonds ne soit pas interprétés comme un appuis. Ca c'est meme presque facultatifs si l'action déclenché est synchrone, mais c'est plus 'propre'.

Ceci dit, tu mets du code (ce qui est plutôt rare ici) et quel qu'il soit, c'est toujours instructif.
Le premier ennemi de la connaissance n’est pas l’ignorance, c’est l’illusion de la connaissance (S. Hawking).

MSG
Raspinaute
Messages : 119
Enregistré le : ven. 26 déc. 2014 18:31

Re: Le bouton poussoir

Message par MSG » sam. 1 févr. 2020 19:31

Bonsoir ,

Le principe de l'anti-rebond par tempo (SLEEP) n'est valabe que si l'on a qu'un seul bouton à surveiller .
Si plusieurs boutons , ça devient ingérable car le programme devient trop lent .
J'ai fait de l'automatisme et je sais que le traitement automate doit se faire sans entrave de temps pour les autres boutons (entrées).

De plus , pour répondre au problème de l'auteur du topic , il veut capturer l'instant furtif de relâcher .
D'où ma façon de faire :

On lit le bit GPIO et on le place , sans a priori , à la suite dans un Registre à décalage .
Les bits sont alors décalés vers la gauche pour laisser place , à droite , au bit GPIO lu .
On peut de cette façon avoir sous la mains , les 4 états d'un contact :
Bas , Appuis (Front montant) , Haut et relâché (Front descendant) .

Code : Tout sélectionner

>>> tableau (2)
Dec , Binaire    , Etat
  0 ,        0   , OFF
  1 ,        1   , Front Montant (appuis)
  2 ,       10   , Front Descendant (relâché)
  3 ,       11   , ON 
>>>
Cycle du Registre à 2 bits : 0, 1, 3, 2, 0, etc

en ajoutant plus de bits dans ce registre , on peut détecter les rebonds (pour des entrées pouvant être parasitées ) et décider de quoi faire .

Code : Tout sélectionner

>>> tableau (3)
Dec , Binaire    , Etat
  0 ,        0   , OFF
  1 ,        1   , OFF
  2 ,       10   , Rebond D
  3 ,       11   , Front Montant (appuis)
  4 ,      100   , Front Descendant (relâché)
  5 ,      101   , Rebond M
  6 ,      110   , ON 
  7 ,      111   , ON 
Cycle du registre à 3 bits : 0, 1, 3, 7, 6, 4, 0, etc
Toute autre valeur doit être considérée comme Rebond et aitre traitée dans la foulée .

Code : Tout sélectionner

>>> tableau (4)
Dec , Binaire    , Etat
  0 ,        0   , OFF
  1 ,        1   , OFF
  2 ,       10   , Rebond D
  3 ,       11   , OFF
  4 ,      100   , Rebond D
  5 ,      101   , Rebond D
  6 ,      110   , Rebond D
  7 ,      111   , Front Montant (appuis)
  8 ,     1000   , Front Descendant (ralâché)
  9 ,     1001   , Rebond M
 10 ,     1010   , Rebond M
 11 ,     1011   , Rebond M
 12 ,     1100   , ON 
 13 ,     1101   , Rebond M
 14 ,     1110   , ON 
 15 ,     1111   , ON 
>>> 
Cycle du registre à 4 bits : 0, 1, 3, 7, 15, 14, 12, 8, 0, etc
Toute autre valeur doit être considérée comme Rebond et aitre traitée dans la foulée .
Le test relâcher peut être alors affecté à une fonction spécifique telle que celle-ci :

Code : Tout sélectionner

def Relache (mot , long=3):
    D = 2**(Long-1)
    if mot == D :
        return True
    else :
        return False
mot = Le mot binaire stocké , long de 2 , 3 ou 4 bits .
long = longueur du mot qui permet de déterminer la position du moment Relâché .

J'aurais pu tout aussi bien mettre la valeur correspondant au moment "Relâcher" , mais ce n'est pas évolutif si l'on change de tableau .

Oui , je met du code , mais je ne suis pas un spécialiste .
Ça peut éveiller certains ... bien souvent , quand on aborde les calculs , surtout les Racines carré , puissances , fractions et autres , il ne reste plus grand monde . :D
Je n'ai pourtant pas été bon élève , encore moins un matheux

MSG
Raspinaute
Messages : 119
Enregistré le : ven. 26 déc. 2014 18:31

Re: Le bouton poussoir

Message par MSG » sam. 1 févr. 2020 20:26

Puisqu'on est dans le dossier Python et que vous aimez le codage , je vous met mon programme (ORIGINAL) qui affiche le(s) tableau(x) .

Code : Tout sélectionner

#!/usr/bin/python3

def tableau (bits=3):
    if bits < 2 : return 

    nb = 2** bits   # nombre de combinaisons binaire
    MB = nb - 1     # valeur Maximale Binaire
    FD = nb >> 1    # Front Descendant (milieur de tableau)
    FM = FD - 1     # Front Montant (milieu de tableau)

    
                    # Affichage tableau
    for n in range (nb):
        if n == 0 : print ("Dec , Binaire\t , BS, RS, Etat")

                    # Gestion des Etats logiques 
        if n & FD :           # Etat du bit le plus à gauche
            etat = "ON "
        else : 
            etat = "OFF"

        if   n == FM :          # Front Montant
            etat += "\tFront M"
        if n == FD :          # Front Descendant
            etat += "\tFront D"

        BS = len(bin(n)[2:])    # Bits Significatifs 
        RS = len(bin(n^MB)[2:]) # Reverse Significatifs

        if bits > 2:
            
                    # Détection des rebonds descendants
            if n > 0 and n <= FM :
                if n != 2** BS - 1:         # Bits à droite toujours à 1 
                    etat += "\tRebond Descendant"
                else : 
                    etat += "\tOK"
                    
                    # Détection des rebonds montants
            if n >= FD and n < MB : 
                if n & (2** RS - 1) != 0 :  # Bits à droite toujours à 0
                    etat += "\tRebond Montant"
                else : 
                    etat += "\tOK"

        print ("%3i , %8s\t , %2i , %2i , %s" %(n, bin(n)[2:], BS, RS, etat))



# Test
tableau(4)
Edit : 1er tableau obsolète , voir le second tableau suite modification du preogramme .
En le copiant dans un fichier (le mien se nomme tableau.py) puis en l'exécutant , celui-ci devrait vous afficher le résultat suivant :

Code : Tout sélectionner

[manu@localhost Prog_python]$ python3 tableau.py
Dec , Binaire    , BS, RS, Etat
  0 ,        0   ,  1 ,  4 , OFF
  1 ,        1   ,  1 ,  4 , OFF        OK
  2 ,       10   ,  2 ,  4 , Rebond Descendant
  3 ,       11   ,  2 ,  4 , OFF        OK
  4 ,      100   ,  3 ,  4 , Rebond Descendant
  5 ,      101   ,  3 ,  4 , Rebond Descendant
  6 ,      110   ,  3 ,  4 , Rebond Descendant
  7 ,      111   ,  3 ,  4 , Front M    OK
  8 ,     1000   ,  4 ,  3 , Front D    OK
  9 ,     1001   ,  4 ,  3 , Rebond Montant
 10 ,     1010   ,  4 ,  3 , Rebond Montant
 11 ,     1011   ,  4 ,  3 , Rebond Montant
 12 ,     1100   ,  4 ,  2 , ON         OK
 13 ,     1101   ,  4 ,  2 , Rebond Montant
 14 ,     1110   ,  4 ,  1 , ON         OK
 15 ,     1111   ,  4 ,  1 , ON 
[manu@localhost Prog_python]$ 
Edit du programme et nouveau tableau ci dessous .
Les Rebonds ne sont pas un état logique , mais plutôt un évènement à traiter pour les supprimer .
Au rebonds 2 et 6 , forcer les bits à zéro .
Au rebonds 9 et 13 , forcer les bits à un .
Les rebonds 4, 5, 9 et 11 sont impossibles , car ça voudrait dire qu'un rebond est passé au travers du filtrage .

Code : Tout sélectionner

[manu@localhost Electricité]$ python3 tableau.py
Dec , Binaire    , BS, RS, Etat
  0 ,        0   ,  1 ,  4 , OFF
  1 ,        1   ,  1 ,  4 , OFF        OK
  2 ,       10   ,  2 ,  4 , OFF        Rebond Descendant
  3 ,       11   ,  2 ,  4 , OFF        OK
  4 ,      100   ,  3 ,  4 , OFF        Rebond Descendant  <= impossible car bit1 pollué 
  5 ,      101   ,  3 ,  4 , OFF        Rebond Descendant  <= impossible car bit1 pollué 
  6 ,      110   ,  3 ,  4 , OFF        Rebond Descendant  
  7 ,      111   ,  3 ,  4 , OFF        Front M OK
  8 ,     1000   ,  4 ,  3 , ON         Front D OK
  9 ,     1001   ,  4 ,  3 , ON         Rebond Montant
 10 ,     1010   ,  4 ,  3 , ON         Rebond Montant  <= impossible car bit1 pollué 
 11 ,     1011   ,  4 ,  3 , ON         Rebond Montant  <= impossible car bit1 pollué 
 12 ,     1100   ,  4 ,  2 , ON         OK
 13 ,     1101   ,  4 ,  2 , ON         Rebond Montant
 14 ,     1110   ,  4 ,  1 , ON         OK
 15 ,     1111   ,  4 ,  1 , ON 
[manu@localhost Electricité]$
PS : je suis avec une version Linux qui a python 2.7 par défaut , d'où l'appel à python3 .
Modifié en dernier par MSG le dim. 2 févr. 2020 21:03, modifié 4 fois.

Bud Spencer
Raspinaute
Messages : 1089
Enregistré le : lun. 15 août 2016 21:38

Re: Le bouton poussoir

Message par Bud Spencer » dim. 2 févr. 2020 11:06

Parce que tu t’imagines que tu peux lire l’état de plusieurs boutons en simultané avec un bout de code en python et en plus en compter les rebonds ? Laisse tomber tout ça parce que la tu t’embrouilles complètement pour un truc qui ne peut pas marcher pour ça. Tant que tu t’amuses à passer des valeurs a une fonction pour quelle t’affiche des trucs à l’écran, ç’est joli, mais c’est totalement inutilisable pour gérer l’état d’un bouton.

Déjà, tu peux oublier tout de suite l’idée de compter les rebonds. Meme avec du code de bas niveau compilé et hyper optimisé des rebonds pourraient passer au travers alors ne t’imagines meme pas pouvoir le faire en python. Il peut se produire plusieurs rebonds successifs durant le simple temps pris par l’exécution d’une seule instruction de ton programme. Ensuite, meme si c’était le cas, tu ne peux pas décider arbitrairement du nombre de rebond qu’il y aura. Ce n’est pas une constante, c’est totalement aléatoire. Il peut ne pas y en avoir du tout comme il peut y en avoir 1,2,3 … 10 ou plus encore, donc un comptage de ceux ci ne sert a rien.
Le premier ennemi de la connaissance n’est pas l’ignorance, c’est l’illusion de la connaissance (S. Hawking).

MSG
Raspinaute
Messages : 119
Enregistré le : ven. 26 déc. 2014 18:31

Re: Le bouton poussoir

Message par MSG » dim. 2 févr. 2020 20:33

Bonsoir ,

Non , je ne cherche pas à compter les rebonds , c'est pas le but de mon tableau .

C'est juste de faire une table de vérité pour analyser les combinaisons probables et éliminer les combinaisons improbables .

Les probables sont les cycles suivants :
Appuis avec 1er rebond = 0, 1, 2 => forcer à 0b0000
Appuis avec 2eme rebond = 0, 1, 3, 6, => forcer à 0b0000
Appuis avec 3eme rebond = 0, 1, 3, 7, 14 => forcer à 0b0000 ou laisser tel quel si considéré comme Relâché
Appuis sans rebond = 0, 1, 3, 7, 15

Relâché avec 1er rebond = 15, 14, 13 => forcer à 0b1111
Relâché avec 2er rebond = 15, 14, 12, 9 => forcer à 0b1111
Relâché avec 3er rebond = 15, 14, 12, 8, 1 => forcer à 0b111 ou laisser tel quel si considéré comme appuyé
Relâché sans rebond = 15, 14, 12, 8, 0

Si les 3emes rebonds sont tolérés on aura des cycle rapides sans rebonds .
OFF ... 0, 1, 3, 7, 15 ...ON... 15, 14, 12, 8, 0 ..OFF.. 0, 1, 3, 7, 15 ..ON... 15, 14, 12, 8, 0 ..OFF..
OFF ... 0, 1, 3, 7, 14, 12, 8, 0 ....OFF
ON ... 15, 14, 12, 8, 1, 3, 7, 15 ... ON

L'état logique du contact est OFF si valeur <= 7 ; ON si valeur >=8 , d'où la correction du tableau et du programme précédent .

Les rebonds doivent être traités après chaque insertion de bit .
D'où des valeurs suivantes qu'on ne trouvera jamais dans le registre si tout fonctionne sans pépin .
(4, 5, 10, 11) qui laisserait pensé que le filtrage des rebonds n'a pas fonctionné .

MSG
Raspinaute
Messages : 119
Enregistré le : ven. 26 déc. 2014 18:31

Re: Le bouton poussoir

Message par MSG » mer. 5 févr. 2020 09:47

Bonjour ,

C'est tout moi , je veux courir avant de savoir marcher .

pour un usage normal du bouton , le fonctionnement serait le suivant :

Image

Rien ne vaut , une petite simulation .

Code : Tout sélectionner

reg_bit = lambda reg, bit : ((reg << 1) + bit) & 0b11
ON = lambda reg : (reg & 0b1) is 1
UP = lambda reg : reg is 0b01
DN = lambda reg : reg is 0b10

MSG
Raspinaute
Messages : 119
Enregistré le : ven. 26 déc. 2014 18:31

Re: Le bouton poussoir

Message par MSG » mer. 5 févr. 2020 10:26

Bud Spencer a écrit :
dim. 2 févr. 2020 11:06
Parce que tu t’imagines que tu peux lire l’état de plusieurs boutons en simultané avec un bout de code en python et en plus en compter les rebonds ?
C'est ce que fonts les API (Automates Programmables Industriels) , les entrées sont lus d'un coup (registre parallèle => série) , traités par le programme et ensuite les sorties sont écrites d'un coup (registre série => parallèle ) .
Avec le RPi , je ne crois pas que cela soit faisable en l'état , à moins de construire une carte E/S synchrone sur le port SPI .

On peut faire du port synchrone en I2c , mais seulement avec quelques composants (registres 8 ou 16 bits voir plus si ça existe) .

MSG
Raspinaute
Messages : 119
Enregistré le : ven. 26 déc. 2014 18:31

Re: Le bouton poussoir

Message par MSG » mer. 5 févr. 2020 19:03

Et maintenant avec la gestion du rebond ! :D :D :D

Image

Le ON et autres signaux sont décalés mais restent de la taille de l'appuie

Code : Tout sélectionner

reg_bit = lambda reg, bit : ((reg << 1) + bit) & 0b111
ON = lambda reg : (reg & 0b010) is 0b010
UP = lambda reg : reg is 0b011
DN = lambda reg : reg is 0b100

action = "s        a aaaaaaa         aaaaa      "
bouton = 0

for n in action :
    if n is "s" : print ("Action , reg ,   on  ,  up  ,   dn  ")
    if n is 'a' :
        appuis = "appuis"
        bouton = reg_bit (bouton, 1)
    else :
        appuis = "      "
        bouton = reg_bit (bouton, 0)
    
    if bouton is 0b10 : 
        bouton = 0 
        rebond = "rebond"
    else :
        rebond = ""
   
    print ("%5s , %3s , %5s , %5s , %5s , %5s"  % (appuis, bin(bouton)[2:], \
        ON(bouton), UP(bouton), DN(bouton), rebond ))
Je pense que ça ne sert à rien d'aller plus loin dans la rechercher des rebonds au delà .
Modifié en dernier par MSG le jeu. 6 févr. 2020 14:13, modifié 1 fois.

Bud Spencer
Raspinaute
Messages : 1089
Enregistré le : lun. 15 août 2016 21:38

Re: Le bouton poussoir

Message par Bud Spencer » jeu. 6 févr. 2020 09:35

Je vois que tu as découvert les expressions lambda, c'est bien.

tu peux en jouer pour ta conversion en gray

Code : Tout sélectionner


gray = lambda i: i^(i>>1)

print (gray(15))

Le premier ennemi de la connaissance n’est pas l’ignorance, c’est l’illusion de la connaissance (S. Hawking).

MSG
Raspinaute
Messages : 119
Enregistré le : ven. 26 déc. 2014 18:31

Re: Le bouton poussoir

Message par MSG » jeu. 6 févr. 2020 14:30

Bonjour ,

Lambda allège le code pour des petites fonctions simples (1 ligne) .

Pour le décode , ça ne tient pas dans une fonction lambda .

On peut l'écrire aussi :

Code : Tout sélectionner

# python 3 : gray = lambda n : n ^ (n//2)  
# python 2 : gray = lambda n : n ^ (n/2)   

Répondre

Retourner vers « Python »