iznobe
Posts: 148
Joined: Sun Feb 05, 2017 4:14 pm

[RESOLU] python : comment eviter les faux positifs sur add_event_detect

Thu Jun 27, 2019 9:16 am

Bonjour ,

voici un script qui n ' est surement pas parfait :?

sur le long therme j ' ai parfois de faux positifs de detection event , il ne s' agit pas de rebond car le flotteur ne bouge pas dans les tests, une solution pour eviter ce phenomene ?

Code: Select all

#! /usr/bin/python
# coding: utf-8

import RPi.GPIO as GPIO
import time
from datetime import datetime

GPIO.setmode(GPIO.BOARD)

pin_flotteur=36
GPIO.setup(pin_flotteur, GPIO.IN, pull_up_down=GPIO.PUD_UP) # en mode entree Tout Ou Rien

# Fonctions
def sendmail (): # fonction qui envoie les mails
    import smtplib
    from email.mime.multipart import MIMEMultipart
    from email.mime.text import MIMEText
########################################################################

time.sleep(0.5) # pause de demarrage
GPIO.add_event_detect(pin_flotteur, GPIO.BOTH, bouncetime=1000) # GPIO.FALLING GPIO.BOTH GPIO.RISING  , callback=my_callback

while True :# a utiliser a la place de la fonction callback pour le moment
    state = GPIO.input(pin_flotteur) # lecture etat de l ' entree
    
    if not state : # l ' eau fait monter le flotteur et coupe le contacteur relais
        #GPIO.remove_event_detect(pin_flotteur)
        print("il ya une fuite d' eau")
        #sendmail()
        now=(datetime.now().strftime("%d/%m/%Y %H:%M:%S"))
        fichier = open("/home/pi/projets_auto/logs/envoi_mail_auto.log", "a")
        fichier.write("le flotteur est passe en position haute a : "+ now+"\n")
        fichier.close()
        while not state : # tant qu on est en etat bas donc flotteur en position haute, on attend qu il redescende.
            state = GPIO.input(pin_flotteur) # lecture etat de l ' entree
            time.sleep(1)
    time.sleep(1) # eviter surcharge proc
# a utiliser a la place de la fonction callback pour le moment
voici le log associé :

Code: Select all

le flotteur est passe en position haute a : 27/06/2019 11:14:42
le flotteur est passe en position haute a : 27/06/2019 11:16:37
le flotteur est passe en position haute a : 27/06/2019 11:17:31
le flotteur est passe en position haute a : 27/06/2019 11:19:11
le flotteur est passe en position haute a : 27/06/2019 11:20:27
le flotteur est passe en position haute a : 27/06/2019 11:20:46

le montage est le suivant :
3.3v => contacteur => resistance 1 kohms => pin 36 ( physique )
la resistance est-elle trop elevee ? le montage n ' est pas bon ?
quel peut etre le probleme selon vous ?
Last edited by iznobe on Mon Jul 01, 2019 2:08 pm, edited 1 time in total.

ernesto
Posts: 131
Joined: Thu Jul 19, 2012 10:09 am

Re: python : comment eviter les faux positifs sur add_event_detect

Thu Jun 27, 2019 4:39 pm

A ce que je vois cela ne devrait pas fonctionner du tout, en effet:
Le gpio 36 est relié à une résistance de pull up et le montage applique 3.3V sur le gpio 36 lorsque le contacteur se ferme. Dans ces conditions le gpio ne peut rien détecter.
GPIO.setup(pin_flotteur, GPIO.IN, pull_up_down=GPIO.PUD_UP) # en mode entree Tout Ou Rien
3.3v => contacteur => resistance 1 kohms => pin 36 ( physique )
Pour que cela puisse fonctionner il y a deux solutions
1) pull up et 0v sur le contacteur
GPIO.setup(pin_flotteur, GPIO.IN, pull_up_down=GPIO.PUD_UP) # en mode entree Tout Ou Rien
0v => contacteur => resistance 1 kohms => pin 36 ( physique )
2) pull down et 3.3 v sur le contacteur
GPIO.setup(pin_flotteur, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) # en mode entree Tout Ou Rien
3.3v => contacteur => resistance 1 kohms => pin 36 ( physique )
Préférer le câblage 1 car en électronique on n'aime pas bien que l'alimentation se promène trop loin dans des câbles.

Nota: avec les infos que vous donnez il ne devrait pas y avoir de détection si c'est le cas cela peut être dû à des parasites, la longueur des câbles ...

tqhien
Posts: 35
Joined: Thu Feb 02, 2012 10:07 am

Re: python : comment eviter les faux positifs sur add_event_detect

Fri Jun 28, 2019 9:30 am

Bonjour,

Alors j'ai un peu répondu sur ton autre post, mais je remets ma réponse ici.

Théoriquement un interrupteur, c'est ouvert ou fermé. Dans la réalité, entre le passage de l'un à l'autre, il y a une foule de micro coupures (de rebond). Selon l'interrupteur, ces rebonds durent plus ou moins longtemps. Il faut donc procéder à une élimination de ces artefacts, c'est ce qu'on appelle le debouncing. Elle s'effectue en deux étapes : dans la déclaration du add_event_detect, le paramètre bouncetime définit qu'il faut ignorer deux appels rapprochés. Et dans ton callback, tu vérifies au bout d'un certain temps qu'on a bien changé d'état.

La trame du traitement est alors la suivante :

Code: Select all

import RPi.GPIO as GPIO

mon_gpio = 17 #quel pin à surveiller

def my_callback(channel):
    GPIO.remove_event_detect(channel) #on neutralise les interruptions sur ce gpio pendant le traitement
    print('Bouton appuye')
    b4_time = time.time() # a quel moment a -t-on appuye
    t = time.time() - b4_time
    time.sleep(.1) # on va attendre pour confirmer ou non l'appui
    while not GPIO.input(channel) :# on attend le retour du bouton : soit on est pas rentrée dans la boucle=artefact, soit on y est, on attend le relaché
         t = time.time() - b4_time
         time.sleep(.1) # on scrute toutes les .1s
     if t >= .1:
          faire_quelque_chose()
    GPIO.add_event_detect(channel,GPIO.FALLING,callback=input_left_callback,bouncetime=50) # onréactive la détection
    
    
GPIO.add_event_detect(mon_gpio,GPIO.FALLING,callback=input_left_callback,bouncetime=50) #on déclare le callback pour l'interruption associée à mon gpio

while (True) : # boucle principale. ya pas grand chose à faire vu qu'on utilise les interruptions
    pass
Hien.

iznobe
Posts: 148
Joined: Sun Feb 05, 2017 4:14 pm

Re: python : comment eviter les faux positifs sur add_event_detect

Mon Jul 01, 2019 8:25 am

Bonjour et merci a vous deux pour votre participation ;)

Alors effectivement , j ' avais pas compris cet histoire de pull_up ( pourtant pas faute d' en avoir lu sur le sujet ) mais votre explication , m ' a enfin permis de comprendre ce qui se passait au niveau du micro controlleur : le pull_up UP , simule en fait un etat logique haut sur le pin concerné , et donc lorsqu ' on passe physiquement en etat bas ( a nous de brancher correctement ) le programme execute le code dans la fonction de call_back.

Ensuite j ' ai compris , comment faire ce fameux double debounce qui permet d' eviter les faux positifs , et j' ai donc readapter mon code en fonction .

Mais je pense que je fais encore des choses pas comme il faut , ou bien le pi a subi des avaries par ma faute , mais ca ne fonctionne pas comme ca le devrait , bien que ca se rapproche du fonctionnement attendu , le processus prend un coeur du proc a 100 % :mrgreen:

voici mon code modifié :

Code: Select all

#! /usr/bin/python
# coding: utf-8

import RPi.GPIO as GPIO
import time
from datetime import datetime

GPIO.setmode(GPIO.BOARD) # board = emplacements physiques , BCM emplacements logiques du proc

# les pins 15 , 8 , 36 sont inutilisables ...
global pin_flotteur
pin_flotteur=15
#TEST#
pin_test=36
GPIO.setup(pin_test,GPIO.OUT)
#TEST#
GPIO.setup(pin_flotteur, GPIO.IN, pull_up_down=GPIO.PUD_UP) # en mode entree Tout Ou Rien
#GPIO.setup(GPIO_LEFT, GPIO.IN, pull_up_down=GPIO.PUD_UP)
# On se met en pullup, l'état du GPIO est donc à 1 par défaut, on détectera un appui lorsqu'il passe à zero (et donc FALLING)
def my_callback(pin_flotteur): # fonction de detection etat du pin en entree
    GPIO.remove_event_detect(pin_flotteur) # on évite un autre appel pendant qu'on traite celui déjà présent
    #global state
    
    time.sleep(5) # ici on faut un debounce : on attend 0.1s pour confirmer ou non l'appui
    state = GPIO.input(pin_flotteur) # lecture etat de l ' entree
    print(state)
    
    if not state :
        print("le flotteur est en position haute")
        #sendmail()
        now=(datetime.now().strftime("%d/%m/%Y %H:%M:%S"))
        fichier = open("/home/pi/projets_auto/logs/envoi_mail_auto.log", "a")
        fichier.write("le flotteur est passe en position haute a : "+ now+"\n")
        fichier.close()
    else : # le flotteur est repasse en position basse , donc le contacteur ( laisse passer le courant) remet le pin a 1
        GPIO.add_event_detect(pin_flotteur, GPIO.BOTH, callback=my_callback, bouncetime=1000) # on remet la détection maintenant que le traitement a été fait
        
    while not state :# on attend le retour du contacteur.
                     # soit on ne rentre pas dans la boucle: c'était un artefact, 
                     # soit on y rentre et on va tester la durée
        state = GPIO.input(pin_flotteur) # lecture etat de l ' entree
        time.sleep(2)

    else : # le flotteur est repasse en position basse , donc le contacteur ( laisse passer le courant) remet le pin a 1
        GPIO.add_event_detect(pin_flotteur, GPIO.BOTH, callback=my_callback, bouncetime=1000) # on remet la détection maintenant que le traitement a été fait
########################################################################

GPIO.add_event_detect(pin_flotteur, GPIO.BOTH, callback=my_callback, bouncetime=1000) # GPIO.FALLING GPIO.BOTH GPIO.RISING

while (True) :
    pass # ou affichage d'infos, etc
    
GPIO.cleanup()
avec ce code , on arrive a faire des actions une seule fois , grace a : " if state : "
avec le while on verifie le nouveau changement d ' etat , et dans le else on repart du debut comme si de rien n ' etait :D

Ca a l ' air de fonctionner maintenant :D ,

Par contre sur mon pi 3 , le processeur a un coeur a 100 % , est normal ? la meme chose chez vous pour votre fonction callback ? ca me parait beaucoup.

Je vous remercie tous les 2 pour votre aide et vous tiens au courant :lol:

tqhien
Posts: 35
Joined: Thu Feb 02, 2012 10:07 am

Re: python : comment eviter les faux positifs sur add_event_detect

Mon Jul 01, 2019 1:14 pm

Salut,

Pour le processeur à 100%, c'est à cause du "pass" dans la boucle principale. Le programme ne fait rien, mais il le fait à fond ;) Normalement, je fais un time.sleep(.2) ou tout autre valeur à la place du pass pour réduire la charge processeur entre 2 affichages de mes infos.

Hien.

iznobe
Posts: 148
Joined: Sun Feb 05, 2017 4:14 pm

Re: python : comment eviter les faux positifs sur add_event_detect

Mon Jul 01, 2019 2:05 pm

Salut
Merci pour cette precision !

effectivement apres avoir planté un sleep a la place ca va beaucoup mieux :D

je ne savais pas que ne rien faire etait autant fatiguant et bouffeur de ressources pour un processeur :lol:

merci beaucoup pour votre aide en tout cas , il ne me reste plus qu ' un detail a regler : le lancement du script au demarrage .

j ' ai edité mon fichier /etc/rc.local dans raspbian et ajouter une ligne de facon a ce qu ' il devienne :

Code: Select all

# lancement script personnalise envoi mail auto en python
python "/home/pi/projets_auto/python/testeur.py" &

# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
  printf "My IP address is %s\n" "$_IP"
fi

exit 0
mais apres reboot dans un terminal si je passe la commande top , je ne vois pas de process avec le nom python, je suppose donc que ca ne fonctionne pas , pourtant la ligne : python "/home/pi/projets_auto/python/testeur.py" & passe dans un terminal et lance le tout normalement .

une idee svp ?

EDIT : finalement apres un deuxieme reboot , tout est ok et fonctionne :P

un grand MERCI pour votre aide a tous !!!

Return to “Français”