Aide vocabulaire

Yo les gens,

Désolé pour le pavé …

En qualité de bidouilleur, j’arrive à faire des choses sans savoir les réaliser réellement.
Et je manque de connaissances, ne serait-ce qu’en vocabulaire.
Alors même que le vocabulaire idoine permet la recherche adaptée.

Je viens donc, pour une fois, demander de l’aide.
En effet, je ne trouve pas car je crois que je ne sais pas nommer ce que je cherche :sunglasses:

Prenons un exemple.
Je fais un script python
J’ai une boucle While (car ça doit tourner indéfiniment)
Ça affiche un accueil (une image et du texte en surimpression)
Ça passe en attente d’un appui sur le GPIO 24 (bouton noir)
Si 24 n’est pas pressé, rien ne se passe
Si 24 est pressé,
alors :

  • prise d’une photo
  • renommage et enregistrement de la photo
  • affichage de la photo
  • impression de la photo
  • affichage de l’accueil

Ce déroulement est logique et simple ; je sais faire ; ça fonctionne.

Maintenant,
Je tente une boucle While qui affiche un accueil (une image et du texte en surimpression)
ça passe en attente d’un appui sur le GPIO 24 (bouton noir)
Si 24 n’est pas pressé, rien ne se passe
Si 24 est pressé,
alors :

  • prise d’une photo
  • renommage et enregistrement de la photo
  • affichage de la photo
    –> mise en pause de la boucle initiale pour entrer dans une autre boucle (boucle2)
    Affichage du texte « enregistrer+imprimer photo ; oui=blanc / non=rouge »
    1 - oui (GPIO26 pressé), alors
  • impression de la photo
  • sortie de la boucle2
  • affichage de l’accueil (retour dans la boucle initiale)
    2 - non (GPIO18 pressé), alors
  • Effacement de la photo
  • sortie de la boucle2
  • affichage de l’accueil (retour dans la boucle initiale)

Pour le moment, je n’ai pas réussi.
je peux bloquer une boucle lancée par GPIO24 en attendant un appui sur GPIO26 puis GPIO18 avant de revenir à la boucle, mais c’est une enchaînement bête alors que je voudrais du conditionnel.
Par exemple, j’ai fais un script simpliste :
Au lancement du script, affichage d’un écran d’accueil
si 24 pressé, alors j’ai une image d’un bouton noir
ça reste là
Si j’appuie sur 24 ou 26 = rien
Si j’appuie sur 18 = image d’un bouton rouge
ça reste là
Si j’appuie sur 18 ou 24 = rien
Si j’appuie sur 26 = image d’un bouton blanc
ça reste là
Si j’appuie sur 24 ça recommence.
J’ai donc une boucle mais sans les « conditions différentielles » ; juste en « suites »(termes appropriés ???)

Question :
Comment s’appelle réellement ce que je cherche à faire ?
Des conditions en cascade ?
Des conditions imbriquées ?
Autre terme ?

Merci pour vos lumières,
(vous me connaissez, je cherches des pistes ; pas des solutions toutes faites sans explications :wink: )

++

Salut,
Ce que tu as besoin, c’est de programmer une machine d’état, ou state machine en anglais

Salut @tynnor

Merci pour ton intervention.

Je venais de faire un script un peu moins pire avec du

  • While
    • if (24)
      • if (18)
      • esle (26)

Au lancement du script, affichage d’un écran d’accueil
si 24 pressé, alors j’ai une image d’un bouton noir
ça reste là
Si j’appuie sur 24 ou 26 = rien
Si j’appuie sur 18 = image d’un bouton rouge
ça reste là
Si j’appuie sur 18 ou 26 = rien
(mais je vois dans le terminal que ma boucle reprend)
Si j’appuie sur 24 = image d’un bouton noir
Et Ceatera
donc, ce n’est pas ça :slight_smile:

Merci pour ton axe de recherche sur machine d’état ou state machine.
Bon, j’arrête pour ce soir (faut être raisonnable, sinon, je me connais, je vais pousser jusqu’à demain matin :slight_smile: )

++

Yo @Nabla

Ta syntaxe de code en Français suit une logique implacable.:sunglasses:

Tu pourrais afficher ton code Python sur le fofo ?
Genre comme celui ci :

import the necessary packages

from __future__ import print_function
import imutils
import cv2
 
# load the Tetris block image, convert it to grayscale, and threshold
# the image
print("OpenCV Version: {}".format(cv2.__version__))
image = cv2.imread("tetris.png")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 225, 255, cv2.THRESH_BINARY_INV)[1]
 
# check to see if we are using OpenCV 2.X
if imutils.is_cv2():
	(cnts, _) = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
		cv2.CHAIN_APPROX_SIMPLE)
 
# check to see if we are using OpenCV 3
elif imutils.is_cv3():
	(_, cnts, _) = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
		cv2.CHAIN_APPROX_SIMPLE)


# draw the contours on the image
cv2.drawContours(image, cnts, -1, (240, 0, 159), 3)
cv2.imshow("Image", image)
cv2.waitKey(0)

@++

Salut,
Un post intéressant et qui sort de l’ordinaire, d’autant plus qu’on sort de la technique pure pour rentrer dans la structure de code, ce qui est très souvent un problème et un facteur limitant pour tous ceux qui ont une pratique peu expérimentée. Ce n’est ni un problème d’intelligence, ni de compétences techniques ou mathématiques, mais plutôt, oserai-je le dire, un problème d’expérience artisanale en quelque sorte. Pour moi, la bonne structure du code relève plus de l’expérience que de la science, un peu comme en soudure, en couture, ou en cuisine.
Parler d’une machine à états à propos de ton problème, c’est certainement scientifiquement correct (qui suis-je pour imaginer le contester…), mais ça n’apporte pas grand chose de concret. Si tu parles à des développeurs d’un problème de machine à état, la plupart vont te regarder avec de grands yeux, et beaucoup ne comprendront pas vraiment ce que tu cherches.
Je propose plutôt de parler de programmation événementielle. Ceci est venu à la mode avec l’arrivée des premiers systèmes graphiques (xerox d’abord, puis lisa et mac, et enfin windows). L’inconvénient d’une interface utilisateur moderne, c’est qu’il y a un grand nombre d’évènements possibles à gérer (clavier, souris, boutons, cases, gpios, timers, communications, et j’en passe). Impossible de programmer tout ça avec des boucles imbriquées, on arrive à des impossibilités. Dans ton exemple, le traitement des boutons G26 et G18 est imbriqué dans celui du G24. Comment feras-tu si tu veux imbriquer dans un bouton G25 ? Tu seras obligé de créer des fonctions ou des classes et ceci ne règlera que partiellement le problème car tu pourrais très bien décider à un moment de faire le contraire et imbriquer le traitement du G24 dans le G26…
Une approche différente serait de gérer chaque évènement l’un à la suite de l’autre, avec une seule boucle (pas d’imbrication) et une série de tests qui se suivent pour savoir quel évènement on doit gérer.
Cela pourrait donner :

  • while True
    • afficher accueil ?
      • affiche accueil
      • sort de la boucle
    • GPIO 24 à traiter ?
      • photo, rename, affichage
      • génère évènement G26
      • sort de la boucle
    • GPIO 18 à traiter ?
      • efface
      • génère évènement affichage accueil
      • sort de la boucle
    • GPIO 26 à traiter ?
      • imprime
      • génère évènement affichage accueil
      • sort de la boucle
    • etc…

De cette manière, tes modules de code sont successifs, tu peux plus facilement les organiser en fonctions ou en méthodes de classes, ton script est carré, facile à maintenir pour un gars limité en neurones comme myself.
Ton post amène un autre problème, celui de la modélisation en pseudo-code. Le pseudo-code, c’est bien gentil, mais ça ne tourne pas. Et comme ça ne tourne pas, on peut toujours prétendre que ça marche, mais on ne peut pas en fournir la preuve. Autant modéliser directement en python, et faire tourner, c’est plus sûr. C’est très difficile de modéliser de façon fiable en pseudo-code. In fine, plus l’algorithme est complexe, plus le risque de faire des erreurs de conception très invalidantes est important.
Espérant t’avoir éclairé, je te souhaite bon courage pour tous tes projets…

Yo,

Merci à tous

Effectivement, le pseudo code … reste … du pseudo code :smiley:

Combien de fois un pseudo code a été parfait aussi longtemps qu’il restait un pseudo code ??? :wink:
C’est là le pb pour un mec possiblement logique mais non codeur …

Le script (un des scripts :smiley: ) :

#!/usr/bin/python3
# -*- coding: utf-8 -*

#on importe les modules nécessaires
import RPi.GPIO as GPIO
import time
from datetime import datetime
from PIL import Image
import pygame
from pygame.locals import *
import os

#on initialise les GPIO en écoute
GPIO.setmode(GPIO.BCM)
GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(24, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(26, GPIO.IN, pull_up_down=GPIO.PUD_UP)

pygame.init()
#screen = pygame.display.set_mode((0,0),pygame.FULLSCREEN)
screen = pygame.display.set_mode((1920,1080),RESIZABLE)
width, height = screen.get_size()

def AfficherTexte(message): # Afficher un Texte en surimpression 
    font = pygame.font.SysFont("verdana", 50, bold=1)
    textsurface = font.render(message, 1, pygame.Color(100,150,200))
    screen.blit(textsurface,(35,40))
    pygame.display.update()

def AfficherPhoto(NomPhoto): # Afficher une image à l'écran
    print("loading image: " + NomPhoto)
    background = pygame.image.load(NomPhoto);
    background.convert_alpha()
    background = pygame.transform.scale(background,(width,height))
    screen.blit(background,(0,0),(0,0,width,height))
    pygame.display.flip()
    
while True : #boucle jusqu'a interruption
  try:
        print ("\n attente boucle")
        
        AfficherPhoto("/home/pi/test-script/accueil.png")
        AfficherTexte("Appuyez sur le bouton noir")

        
        #on attend que le bouton soit pressé
        GPIO.wait_for_edge(24, GPIO.FALLING)
        

        #on génère le nom de la photo avec heure_min_sec
        date_today = datetime.now()
        nom_image = date_today.strftime('%d_%m_%H_%M_%S')

        
        #on déclenche la prise de photo
        os.system('raspistill -w 800 -h 600 -o "/home/pi/test-script/photos/'+nom_image+'.jpeg" -q 100')

        AfficherPhoto("/home/pi/test-script/photos/"+nom_image+".jpeg")
        AfficherTexte("OK pour Test")
        time.sleep(5)
        
        GPIO.wait_for_edge(18, GPIO.FALLING)
        print ("18 ?")
        AfficherPhoto("/home/pi/test-script/accueil.png")
        AfficherTexte("GPIO 18 pressé")
        time.sleep(3)

        
        GPIO.wait_for_edge(26, GPIO.FALLING)
        print ("26 ?")
        AfficherPhoto("/home/pi/test-script/accueil.png")
        AfficherTexte("GPIO 26 pressé")
        time.sleep(3)



        if (GPIO.input(24) == 0): #Appui long durant la séquence = sortie de la boucle)
              print ("Arrêt script demandé")
              break  
 

  except KeyboardInterrupt:
    print ('sortie du programme!')
    raise

GPIO.cleanup()           # reinitialisation GPIO

Ce script fonctionne bien
Appui sur 24 = prise de la photo et affichage avec « Test OK » puis ça attend

Si 24 ou 26 appuyé = rien
Obligé d’appuyer sur 18 qui enclenche bien le fond + « GPIO 18 pressé »
Puis ça attend

Si 24 ou 18 appuyé = rien
Obligé d’appuyer sur 26 qui ré-enclenche bien le fond + « GPIO 26 pressé »
Et retour au début

L’idée étant d’avoir un choix appuyez sur 18 ou 26 si vous m’avez suivi :wink:

++

Re,

Pas pu vraiment lire ni tester pour le moment.
Mais je tente par à-coups

#!/usr/bin/python3
# -*- coding: utf-8 -*

#on importe les modules nécessaires
import RPi.GPIO as GPIO
import time
from datetime import datetime
from PIL import Image
import pygame
from pygame.locals import *
import os

#on initialise les GPIO en écoute
GPIO.setmode(GPIO.BCM)
GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(24, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(26, GPIO.IN, pull_up_down=GPIO.PUD_UP)

pygame.init()
#screen = pygame.display.set_mode((0,0),pygame.FULLSCREEN)
screen = pygame.display.set_mode((1360,768),RESIZABLE)
width, height = screen.get_size()

def AfficherTexte(message): # Afficher un Texte en surimpression 
    font = pygame.font.SysFont("verdana", 50, bold=1)
    textsurface = font.render(message, 1, pygame.Color(100,150,200))
    screen.blit(textsurface,(35,40))
    pygame.display.update()

def AfficherPhoto(NomPhoto): # Afficher une image à l'écran
    print("loading image: " + NomPhoto)
    background = pygame.image.load(NomPhoto);
    background.convert_alpha()
    background = pygame.transform.scale(background,(width,height))
    screen.blit(background,(0,0),(0,0,width,height))
    pygame.display.flip()
    
while True : #boucle jusqu'a interruption
  try:
        print ("\n attente boucle")
        
        AfficherPhoto("/home/pi/test-script/accueil_1360x765.png")
        AfficherTexte("Appuyez sur le bouton noir")

        
        #on attend que le bouton soit pressé
        GPIO.wait_for_edge(24, GPIO.FALLING)
        

        #on génère le nom de la photo avec heure_min_sec
        date_today = datetime.now()
        nom_image = date_today.strftime('%d_%m_%H_%M_%S')

        
        #on déclenche la prise de photo
        os.system('raspistill -w 1360 -h 768 -o "/home/pi/test-script/photos/'+nom_image+'.jpeg" -q 100')

        AfficherPhoto("/home/pi/test-script/photos/"+nom_image+".jpeg")
        AfficherTexte("imprimer ? rouge=oui blanc=non")
        time.sleep(5)
        
        if GPIO.wait_for_edge(18, GPIO.FALLING):
          print ("18 ?")
          AfficherPhoto("/home/pi/test-script/accueil_1360x765.png")
          AfficherTexte("impression ok - GPIO 18 pressé")
          time.sleep(3)
        
        elif GPIO.wait_for_edge(26, GPIO.FALLING):
          print ("26 ?")
          AfficherPhoto("/home/pi/test-script/accueil_1360x765.png")
          AfficherTexte("photo annulée - GPIO 26 pressé")
          time.sleep(3)
          
        else:
          AfficherPhoto("/home/pi/test-script/accueil_1360x765.png")
          AfficherTexte("on recommence")



        if (GPIO.input(24) == 0): #Appui long durant la séquence = sortie de la boucle)
              print ("Arrêt script demandé")
              break  
 

  except KeyboardInterrupt:
    print ('sortie du programme!')
    raise

GPIO.cleanup()           # reinitialisation GPIO

Là, j’ai bien l’invitation pour appuyez sur 24 (débuter la boucle)
Une fois 24 pressé, j’ai prise de photo puis affichage photo avec « imprimer ? rouge=oui blanc=non »

Mais je ne peux faire que un appui sur 18 (bouton rouge)
Un appui sur 26 (blanc) ne lance rien.

Une fois 18 pressé, j’ai bien « impression ok - GPIO 18 pressé » qui s’affiche 3 seconde et je repasse au début de la boucle

Bref, tout ce qui suit soit

elif GPIO.wait_for_edge(26, GPIO.FALLING):
  print ("26 ?")
  AfficherPhoto("/home/pi/test-script/accueil_1360x765.png")
  AfficherTexte("photo annulée - GPIO 26 pressé")
  time.sleep(3)
  
else:
  AfficherPhoto("/home/pi/test-script/accueil_1360x765.png")
  AfficherTexte("on recommence")

est non pris en compte.

@tynnor
Et ?

Beaucoup de monde, ici, connaît la traduction en anglais de state machine.

Mais si tu n’exposes pas de façon explicite ce qu’est la programmation, sur une macchina di stato,
les membres du forum seront un peu perdus.

Je ne vois pas ce que tu apportes de concret sur le sujet. A moins d’allez plus loin dans ton argumentation. Comme expliquer pour les néophytes, ce que c’est une « state machine »…

Désolé pour toi, mais ici le sujet concerne un problème relatif a la syntaxe Python.

Mais soyons constructif.
Postes un sujet concret autour du Raspberry, avec un langage de bas ou haut niveau, peu importe.

De plus, tu peux contacter @Nabla, qui gere son blog autour de la PI, histoire de lui exposer tes projets.

P.S @Nabla je t’envoi une patate chaude :wink:

Yo,

Ne pouvant « travailler » que par à-coups, je ne suis pas très productif.
J’ai tenté des modifications de code sur des codes clonés et je me perds (faut que je passe à GitHub).
Pour les states Machines, ça semble intéressant, au moins dans la théorie :

State machines are especially interesting because, among other things, they provide well-defined scenarios and list out the conditions to get to them. This makes it very easy to scope out edge cases and how to handle them, as we are forced to consider every possible scenario our code must fall within.

Et c’est bien ce que je veux : des scénarios bien définis et des conditions pour y accéder.

Il me reste du chemin cependant.
Là, j’exploire les boucles car j’avais dans l’idée ce que proposait @jmbc avec

Mais en fait, je crois que je pèche sur la syntaxe car c’est un échec (partiel, pas total).
Comme dirait @jelopo : RTFM :wink:

++

Il n’est pas vraiment question de programmation événementielle ici. On pourrait toujours adopter une structure de la sorte mais ça sera lourd pour pas grand chose.

Effectivement ce genre de problème se rencontre assez rapidement quand on commence à coder. Heureusement, dans l’orienté objet, il existe un tas de solution pour résoudre ce genre de soucis d’architecture du code : on appelle ça des design pattern ou patron de conception, sujet très documenté sur internet

Pour l’instant je n’ai pas le temps donner un exemple de code, je le ferais peut-être ce soir. (mais ce sera pas du Python). Mais voici un peu de doc sur le sujet :

https://medium.com/datadriveninvestor/state-machine-design-pattern-part-2-state-pattern-vs-state-machine-3010dd0fcf28

Tout plein d’exemple de design pattern :

Voilà un exemple simpliste d’une machine d’état en C ou C++. En suivant un tel modèle, tu arriveras (peut-être sans soucis) à tes fins.
Les noms des états sont évidemment mal choisis ! A toi de l’adapter en fonction de l’application

//déclaration des différents états de la machine d'état
enum STATE{
	STATE_1,
	STATE_2,
	STATE_3,
	STATE_4,
	STATE_5,
	STATE_LAST
};



//contient l'état en cours de la machine d'état
STATE state = STATE_1;

int main(){

	
	while(state != STATE_LAST){

		switch(state){


			case STATE_1:
			{
				afficherAccueil();
				state = STATE_2;
			}
			break;

			case STATE_2:
			{
				//attente appuie sur le bouton
				if(getPressedKey() == GPIO_24){
					state = STATE_3;
				}
			}
			break;


			case STATE_3:
			{
				takePicture();
				pictureProcessing();
				

				//on pose la question à l'utilisateur
				string answer = showText();
				if(getPressedKey() == YES)
					state  = STATE_4;
				else
					state = STATE_5;


			}
			break;


			case STATE_4:
			{
				printPicture();

				//retour au début
				state  = STATE_1;
			}
			break;

			case STATE_5:
			{
				deletePicture();
				state = STATE_1;
			}
			break;

			case STATE_LAST:
			{
				
			}
			break;

		}



	}



	return 0;
}

Bon courage :wink:

Hello,
Je suis sûr qu’une âme charitable va m’expliquer pourquoi ce n’est pas de la programmation événementielle…
Pour ce qui est des design patterns, je suis curieux de savoir lequel s’applique au cas présent, et pendant qu’on y est, un exemple serait bien venu.
Du concret quoi, pas simplement des affirmations.

Si tu avais lu les réponses précédentes ou fais des recherches sur le sujet, tu aurais vu que la machine d’état est un design pattern et qu’il y a un exemple concret …
Je ne donne pas de mon temps pour faire ton apprentissage mais pour donner un coup de main à ceux qui on fait un effort.

Programmation événementielle ça veut tout et rien dire, le pattern observer je le considère comme événementiel. Lorsqu’un événement dans ton code survient, il appelle une fonction dit fonction de callback. Quand on parle de callback, je pense qu’on peut parler de programmation événementiel. Ce mécanisme est utilisé à gogo dans les interfaces graphiques

Yo,

Désolé, je bosse sur des projets variés qui me prennent pas mal de temps et j’ai dû laisser ce sujet (et le forum) de côté.

Je remercie tout le monde pour les avis et pistes.
Connaissant les pédigrées de certains d’entre vous, je me permets de dire que vos compétences ne sont plus à prouver donc je saupoudre de modération :wink:

Mon message était posté dans le but d’avancer et de profiter à tous.
Ok pour du débat, mais en aucun cas ce post ne doit être sujet à « partir en vrille » :sunglasses:

++

Salut,
Bof, une petite vrille de temps en temps, c’est un joli spectacle…

Bonjour à tous,
alors comme l’à dis Nabla, aucun doute ici sur les compétences de qui que ce soit. Au passage merci pour le terme de machine à état, maintenant je connais le nom de ce machin.

Mais au final, comme toujours avec nous les développeurs, tout le monde cherche à savoir ce qui est le plus « dans les règles de l’art », alors que le vrai problème est : « Comment gégé de la compta va pouvoir faire son truc pour demain ? », ou dans notre cas, « Comment Nabla va pouvoir corriger son photomaton rapidement ? ».

Et il me semble, à moi, que le problème de fond de Nabla n’est ni événementiel, ni une machine a états. Encore que @Nabla je te conseillerais de jeter un œil à cette méthode.
GPIO.add_event_detect(10,GPIO.RISING,callback=button_callback) # Setup event on pin 10 rising edge
Qui permet d’appeler une fonction sur l’appui d’un bouton, et donc effectivement il serait possible d’utiliser une machine a états avec ça. Comme ça tout le monde est content, ya de l’événementiel, et de la state machine.

Maintenant, pour en revenir au problème de base, ton code est presque bon.
En fait, ton problème c’est que tu attends un clic sur un bouton, mais tu ne sais pas à l’avance lequel. Hors, tu utilises la méthode GPIO.wait_for_edge. Cette méthode va bloquer ton programme en attendant que le bouton soit appuyé.

C’est pour ça que seul ton bouton 18 et pris en compte, et pas le 26. Car en fait, le bout de code pour le 26 n’est jamais pris en compte. Je m’explique.

Quand tu demandes si le 18 est appuyé, le programme attends indéfiniment jusqu’à ce que ce soit le cas. Il est donc bloqué à cette étape et ne peut rien lire d’autre ! Une fois le bouton cliqué, et bien tu rentres dans ta condition, et donc le elif du bouton 26 n’est jamais lu. Sinon, tu serais obligé de cliqué en plus sur le 26 ^^.

J’ai deux solutions pour toi, une plutôt propre, qui demande de revoir pas mal la logique de ton code et pour le coup utilise de l’évènementiel. Une un peu moins propre, mais probablement plus simple et plus proche de ton code (et donc ta logique) actuelle.

Solution propre :
Une solution élégante serait d’utiliser add_event_detect, qui lui est non bloquant, et de fournir des fonctions à appeler différentes pour le bouton 18 et 26.
Une machine a état n’est pas nécessaire dans ton cas, car ces fonctions ne seront appelée que dans ce cas très précis. Alors, tu pourrais simplement faire comme ça :

Tu fais 4 fonctions :

  1. show_home(), qui affiche ton accueil et demande de cliquer sur 24. Elle utilise wait_for_edge pour détecter l’appuie, et appel la fonction take_picture().
  2. take_picture(), qui prend la photo et affiche le message demandant si on veut imprimer la photo. À la fin de cette fonction, elle appel add_event_detect() sur le 18 qui appellera la fonction print_picture(), en lui passant en paramètre le nom de la photo à imprimer, et add_event_detect() sur le 26 qui appellera la fonction delete_picture() avec le nom de la photo à supprimer.
  3. print_picture(picture_file_path), qui supprime la detection d’event sur 18 et 26, avec cancel_event_detect(18) et cancel_event_detect(26), puis imprime le fichier au chemin picture_file_path, et enfin appel show_home().
  4. delete_picture(picture_file_path), qui supprime la detection d’event sur 18 et 26, avec cancel_event_detect(18) et cancel_event_detect(26), puis supprime le fichier au chemin picture_file_path, et enfin appel show_home().

Et ton programme ? Bah il appel juste show_home() une seule fois, sans boucle infinie, puisque chaque déroulé te ramène à show_home() à nouveau.
Tu peux aussi rajouter un troisième event pour la sortie de la boucle au clic sur 24, comme pour 18 et 26. Sauf que lui n’appellera jamais show_home().

Solution simple :
Tu utilises un système non bloquant pour lire l’état du GPIO, et tu boucles.

Concrètement, après ta question pour imprimer, au lieu d’utiliser wait_for_edge pour lire 18 et 26, tu fais ça :

  1. Tu initialise une variable quit a False avant ta boucle infinie. Et tu rajoutes une condition au début de ta boucle infinie qui dis, si quit, alors break.
  2. Tu ouvre une boucle while True
  3. Tu lis 18 avec GPIO.input(), s’il est à faux, tu imprimes, tu break.
  4. Sinon, tu lis 26 avec GPIO.input(), s’il est à faux, tu supprimes la photo, tu break.
  5. Sinon, tu lis 24 avec GPIO.input(), s’il est à faux, tu passes quit à vrai, tu break.

Cette solution me semble moins élégante, et consomme probablement plus de ressources. Mais elle me semble aussi beaucoup plus simple à comprendre et maintenir.

Par ailleurs, je te conseils de regarder de prêt le paramètre bouncetime de add_event_detect pour éviter les surprises du type imprimer 10 photos d’un coup ^^. Regarde ici : raspberry-gpio-python / Wiki / Inputs.

J’espère que ça aura pu résoudre ton problème :slight_smile:

Yo,

Merci,

Ce projet a été mis de côté du fait de changements non prévus en parallèle.
Ce projet a été « solutionné » à la Nabla c’est à dire par une technique de contournement momentanée.
Elle donne satisfaction (ça fonctionne), même si je n’ai pas le but ultime recherché.

Je garde évidemment cela sous le coude car j’y pense souvent et je devrais, si tout va bien, pouvoir m’y remettre dans peu de temps.

Au plaisir :wink: