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

[ RESOLU ] question debutant sur code python

Tue Jun 25, 2019 4:11 pm

Bonjour je ne comprends pas pourquoi le retour de ce code est :

Code: Select all

Bouton appuye
Bouton appuye
Bouton appuye
Bouton appuye
Bouton appuye
Bouton appuye
Bouton appuye
Bouton appuye
Bouton appuye
Bouton appuye
Bouton appuye
Bouton appuye
Bouton appuye
Bouton appuye
Bouton appuye
Bouton appuye
Bouton appuye
voici le code en question :

Code: Select all

# coding: utf-8

import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BOARD)

pin_flotteur=15
GPIO.setup(pin_flotteur, GPIO.IN) # 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
########################################################################
def my_callback(pin_flot): # fonction de detection etat du pin en entree
    state = GPIO.input(pin_flot) # lecture etat de l ' entree
    if state :
        print("le flotteur est en position haute")
        sendmail()

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

while True:
    if GPIO.event_detected(pin_flotteur):
        print("Bouton appuye")
une explication serait la bienvenue svp

y a t il un moyen de n ' afficher qu ' une seule fois le message "bouton appuye" tout en conservant la boucle bien sur ? si oui lequel svp
Last edited by iznobe on Wed Jul 03, 2019 3:55 pm, edited 1 time in total.

totoharibo
Posts: 4178
Joined: Thu Jan 24, 2013 8:43 am

Re: question debutant sur code python

Tue Jun 25, 2019 8:31 pm

quand tu as détecté position haute, détecte position basse avant d'envoyer à nouveau position haute.

en bash ça serait plus simple, Python est à la mode alors ...

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

Re: question debutant sur code python

Wed Jun 26, 2019 7:18 am

totoharibo wrote:
Tue Jun 25, 2019 8:31 pm
quand tu as détecté position haute, détecte position basse avant d'envoyer à nouveau position haute.

en bash ça serait plus simple, Python est à la mode alors ...
Salut et merci pour ton conseil ,
mais du coup il faudrait que je fasse cela dans la fonction de call_back ou dans la boucle while ?

la ou je ne comprends pas trop , c' est comment j' envoie a nouveau position haute ... desolé pour mon ignorance :cry:

en essayant de traduire mot a mot :

Code: Select all

def my_callback(pin_flot): # fonction de detection etat du pin en entree
    state = GPIO.input(pin_flot) # lecture etat de l ' entree
    if state :
        print("le flotteur est en position haute")
        #sendmail()
        state = GPIO.input(pin_flot) # lecture etat de l ' entree
        if not state :
            state = GPIO.input(pin_flot) # lecture etat de l ' entree

GPIO.add_event_detect(pin_flotteur, GPIO.BOTH, callback=my_callback, bouncetime=1000) # GPIO.FALLING GPIO.BOTH GPIO.RISING
mais bon je ne suis pas sur de moi :D

De plus je ne suis pas sectaire :) en bash ou en python peut m ' importe , j ' ai fait en python car je m ' averti par mail grace a un script en python que j ' ai trouvé sur le net , etant tres debutant , je ne sais pas si en bash c ' est aussi possible :oops:

Et je ne sais pas quel code ecrire ni en bash ni en python pour arriver au resulat escompté :?

Sachant que je voudrais lancé ce script automatiquement au demarrage du pi une fois finalisé , j ' ai testé d 'ajouter une ligne dans le fichier rc.local mais ca n ' avait pas fonctionné en tout cas je n ' ai rien vu dans top qui m ' indiquait que python tournait mais ca c ' est en core un autre probleme .

est ce que cela fait avancer le schmilblik , ou je suis totalement a coté de la plaque ? :

Code: Select all

# coding: utf-8

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BOARD)

pin_flotteur=15
GPIO.setup(pin_flotteur, GPIO.IN) # 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
########################################################################
def my_callback(pin_flot): # fonction de detection etat du pin en entree
    state = GPIO.input(pin_flot) # lecture etat de l ' entree
    if state :
        print("le flotteur est en position haute")
        #sendmail()
        while state :
            state = GPIO.input(pin_flot) # lecture etat de l ' entree
            time.sleep(1)

GPIO.add_event_detect(pin_flotteur, GPIO.BOTH, callback=my_callback, bouncetime=1000) # GPIO.FALLING GPIO.BOTH GPIO.RISING
Mais bon c ' est vilain :evil: , le but du callback etant d' avoir un programme non bloquant et le time.sleep bloque le programme ...
je ne peux donc pas laisser comme ca , car je compte ajouter d' autres fonctions par la suite .

Mais je ne comprends toujours pas pourquoi lorsque je lance le programme je n ' ai pas un seul evenement detecté , mais une suite .......
l ' evenment ne se produisant qu ' une seule fois
serait il possible d' avoir une explication sur ca svp ?

totoharibo
Posts: 4178
Joined: Thu Jan 24, 2013 8:43 am

Re: question debutant sur code python

Thu Jun 27, 2019 6:05 am

la plus belle fille ne peut donner que ce qu'elle a.

Ton projet fait deux choses :
- tester un contact et le signaler
- envoyer un email.

Tester les fonctions l'une après l'autre et ensuite remettre le tout ensemble.

OK faut taper sur le clavier mais le tout ne semble pas exister chez Linux ... ni ailleurs
En plus c'est formateur.

Le problème : l'envie, le besoin (le temps n'est qu'une excuse)

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

Re: question debutant sur code python

Thu Jun 27, 2019 8:09 am

Rebonjour ,
Tester les fonctions l'une après l'autre et ensuite remettre le tout ensemble.
c ' est ce que j ' ai commencé par faire bien avant de venir poster ici :?

est il possible de faire le test du contact en bash et appeller le script python ( send_mail.py) dans le fichier bash ?

ca simplifierait les choses d' apres ce que vous dites...

Mon probleme n ' est ni le temps , ni le besoin , ni l ' envie , c ' est le manque de connaissance au niveau programmation pure et au niveau du potentiel de chaque langage ainsi qu ' en electronique , partant de là evidement je passe pour un noob ( ce qui ne me derange pas ) et des choses qui peuvent paraitre simple pour ceux qui connaissent l ' electronique et la programmation sur le bout des doigts me sont totalement inconnues :?

je suis alller sur le site officiel et fait des recherches quand au fonctionnement de la fonction call backpar exemple ici : https://sourceforge.net/p/raspberry-gpi ... ki/Inputs/

Dans aucun des documents que j' ai pu lire en francais ou en anglais il n ' est mentionné que la fonction callback agit sur le principe d' une boucle , pourtant si le fonctionnement est " normal chez moi " c ' est ce qui me pose probleme , je suis certain que cene doit pas etre si compliqué que ca dans le principe a coder , mais parfois ( quand on manque d' assurance et de connaissance , ce qui est mon cas dans ce domaine ) on ne cherche pas au bon endroit et il y parait une montagne insurmontable tellement de possibilités , de fonctions , de classes , de bibliotheques ...

j ' avoue etre sur ce projet depuis environ 2 ans et demi , ca va certainement vous fait rire , mais comme vous le voyez je persevere , il ne manque vraiment pas grand chose pour qu ' il aboutisse enfin et que je passe a la suite : une programmation horraire qui va gerer differents moteur et mise en route ou arret a heure fixe de differentes unités , j ' avoue que je vais encore galerer un bon moment avant de terminer mon projet , il manquera du materiel etc ... mais cela ne me fait pas peur , ca prendra le temps que ca prendra , mais l ' echec n ' est pas une option envisageable dans mon esprit ;)

une fois que j ' aurais terminez tout cela , je pense que mon savoir dans le domaine aura certainement bien grandi surtout que je pars de rien vu que je n' ai aucune formation ni diplome , j ' apprend tout sur le tas .

pour le moment , j ' ai toujours le meme probleme de base : comment ne faire qu ' une seule iteration dans la boucle avant nouveau changement d' etat , je comprends votre :
quand tu as détecté position haute, détecte position basse avant d'envoyer à nouveau position haute.
mais je n ' arrive pas a l ' implementer au niveau du code par manque de conaissance :roll:
j ' ai enlever la fonction callback pour le moment et pour plus de simplicité voici donc ou j ' en suis :

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) # a utiliser a la place de la fonction callback pour le moment
    
A priori le probleme d ' envoi de plusieurs iterations est en parti resolu , mais je ne sais pas si c ' est la bonne façon de proceder le time .sleep etant bloquant non ?

Merci pour votre contribution a mon probleme.

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

Re: question debutant sur code python

Thu Jun 27, 2019 9:58 am

voici ce que je fait pour transposer en code vos dires :
quand tu as détecté position haute, détecte position basse avant d'envoyer à nouveau position haute.

Code: Select all

#quand tu as détecté position haute,
    if not state : # l ' eau fait monter le flotteur et coupe le contacteur relais
        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()
        
        #détecte position basse
        state = GPIO.input(pin_flotteur) # lecture etat de l ' entree
        if state :
        	# ici comment j ' envoie a nouveau position haute ?
        
merci pour votre aide

totoharibo
Posts: 4178
Joined: Thu Jan 24, 2013 8:43 am

Re: question debutant sur code python

Fri Jun 28, 2019 7:35 am

pour le contact, j'avais fait un truc en bash pas tout à fait pour ton cas mais c'est adaptable.
pour info l: a fonction bouton est en tache de fond.

Code: Select all

#!/bin/bash
#essai de clignotant des  2 couleurs

#init hard
#.	../../init_acquisition
BOUTON_POUSSOIR=9
##################################################################
#init
function init {

echo  "init"
gpio -g mode 9 in
}

##################################################################
#teste BP
function bouton {
#inter
export proc_bouton
#echo "bb"
inter=$(gpio -g read $BOUTON_POUSSOIR )
echo "==$inter=="
( while [ 1 ] ; do
	lit=$(gpio -g read $BOUTON_POUSSOIR )
	if [ $lit -ne $inter ] ; then
		inter=$lit
		echo "**$inter**"
		if  [ $lit -eq 0 ] ; then
			kill -USR1 $$
			echo "---->kill"
		fi
	fi
	sleep 0.1
	done
) &
proc_bouton=$!
}
##################################################################
##################################################################
bouge=0
trap "bouge=1" SIGUSR1
#on démarre
init
echo $$
#inter
bouton
#boucle de fond
while [ 1 ] ; do
	if [ $bouge -ne 0 ] ; then 
		echo "---->bouge" 
		bouge=0
		#break
	fi
	sleep 0.5
done
#arrete procs
kill $proc_bouton

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

Re: question debutant sur code python

Fri Jun 28, 2019 9:18 am

Bonjour,

Alors, voici quelques éléments pour t'aider dans ton projet.

L'utilisation du callback, c'est de générer des interruptions et donc de s'affranchir de la boucle while (ou d'utiliser la boucles while pour faire autre chose, comme affichage de la température, etc). Lorsqu'il y a changement d'état sur le GPIO choisi, on fait les manips (dans ton cas, envoyer le mail) et le programme continue sa partie principale (il continue l'affichage de la température pendant ce temps, dans l'exemple).

Deuxième élément, 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.

Voici donc un bout de code que j'utilise pour tout ça :

Code: Select all

GPIO_LEFT = 27
BOUTON_LEFT     = pygame.K_LEFT # Bouton left
BOUTON_HOME     = pygame.K_HOME # Bouton left long
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 input_left_callback(channel):
    global left_state
    GPIO.remove_event_detect(channel) # on évite un autre appel pendant qu'on traite celui déjà présent
    print('Bouton gauche @{}'.format(time.time())
    left_long_state = False
    b4_time = time.time()
    t = time.time() - b4_time
    time.sleep(.1) # ici on faut un debounce : on attend .1s pour confirmer ou non l'appui
    while not GPIO.input(channel) :# on attend le retour du bouton. soit on ne rentre pas dans la boucle, c'était un artefact, soit on y rentre et on va tester la durée
        t = time.time() - b4_time
        if t >= .1 and t < 2: 
            if not left_state:
                left_state = True
        if t >=2: # appui long
            if not left_long_state:
                pygame.event.post(pygame.event.Event(pygame.KEYDOWN, {'key':BOUTON_HOME}))
                left_long_state = True
                old_t = time.time() - b4_time
            else:
                if t - old_t >= .5 : # appui très long
                    pygame.event.post(pygame.event.Event(pygame.KEYDOWN, {'key':BOUTON_HOME}))
                    old_t = time.time() - b4_time
        time.sleep(.1)
    if t >= .1 and t < 2: #appui simple
        pygame.event.post(pygame.event.Event(pygame.KEYDOWN, {'key':BOUTON_LEFT}))
    print('Bouton gauche pendant {}s'.format(t))
    left_state = False
    left_long_state = False
    GPIO.add_event_detect(channel,GPIO.FALLING,callback=input_left_callback,bouncetime=50) # on remet la détection maintenant que le traitement a été fait
   
GPIO.add_event_detect(GPIO_LEFT, GPIO.FALLING, callback=input_left_callback, bouncetime=50)   

while (True):
    pass # ou affichage d'infos, etc
   
Ce que fait mon bout de code (que j'utilise avec pygame) :
Je simule l'appui sur une touche de clavier selon l'appui sur un bouton : appui court, je simule la flèche gauche, appui long, j'envoie la touche HOME, et si je continue d'appuyer, il envoie Home toutes les demi-secondes. Je n'ai pas remis en début d'extrait les imports nécessaires au fonctionnement. J'espère que tu trouveras tout seul / adapteras pour tes besoins.

Hien.

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

Re: [ RESOLU ] question debutant sur code python

Wed Jul 03, 2019 4:01 pm

Bonjour et Merci a vous 2 ;)

le probleme etait donc du a une erreur de codage voici donc la solution la plus approprié pour mon cas et n ' envoyer qu ' une seule iteration par changement d' etat et ensuite revenir a l ' etat anterieur physique et au niveau du code .

Les commentaires sont là pour expliquer les " subtilites " du code ( pour niveau debutant ;) )

Code: Select all


def my_callback (pin_flotteur) : # gestion des actions en fonction de l ' etat du PIN d' entree
    
    GPIO.remove_event_detect(pin_flotteur) # on évite un autre appel pendant qu'on traite celui déjà présent
    time.sleep(1) # 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
    
    # Si on est toujours dans l' etat haut 
    if not state : # permet de faire les actions une seule fois par cycle de montee descente flotteur grace au time.sleep dans la boucle while
        sendmail()
        ecrire_log("le flotteur est passe en position haute a : ",1)
    
    while not state : # on attend le retour du contacteur.
        ecrire_log("on attend le retour a l ' etat normal du flotteur",0)
        time.sleep(10) # on attend le retour a l ' etat normal du flotteur
        state = GPIO.input(pin_flotteur) # lecture etat de l ' entree
        
        if state :# le flotteur est repasse en position basse , donc le contacteur fait contact et remet le pin a 0
            ecrire_log("le flotteur est en position normale : basse 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  , callback=my_callback
ecrire_log ("Initialisation sur le pin : " + str(pin_flotteur) + ", a : ",1)
Un grand merci a vous pour vos explications , j ' ai etudié le code bash aussi de tres pres , mais m ' y connaiissant moins , j ' ai opté pour le code en python car il ne manquait en fait presque rien pour que le script soit completement fonctionnel .

Oui je sais je suis une faignasse :lol:

Au plaisir ! :D

Return to “Français”