Power Script PIN356ONOFFRESET avec switches SNES d'origine



  • Bonjour à tous,

    Je suis en train de faire une SNES Recalbox, en récupérant évidemment le ON/OFF et Reset d'origine.
    Pris chacun à part, le ON/OFF fonctionne correctement avec PIN56ONOFF et le Reset également avec PIN56PUSH.

    => donc mon câblage est OK sur ces 2 switches :)

    Par contre je bute sur le script PIN356ONOFFRESET, il a un comportement bizarre, même après MAJ 18.04.20, je m'explique :

    Le ON/OFF sur les PINS 5 & 6 :
    => ON, ça s'allume, cool !
    => J'attends un peu et je switch sur OFF, et là rien !
    obligé de refaire un ON (2 secondes) puis un OFF pour que ça s'éteigne... pas cool !

    Le RESET sur les PINS 3 & 9 :
    => Dans le menu, Appui court, reboot , cool !
    => Dans le menu, Appui long, reboot , cool !
    => En jeu, appui court, rien !
    => En jeu, appui long, reboot, cool ! normal ??

    J'ai l'impression que le script PIN356ONOFFRESET ne garde pas en mémoire l'état du switch, d'où l'obligation de refaire un ON puis OFF.
    Pour le Reset, j'ai déjà lu sur un autre post que ça ne fonctionnait pas non plus en jeu pour une autre personne, alors je suis moins étonné.

    Vous pouvez m'éclairer SVP ?

    Merci :)



  • Je me réponds à moi-même du coup...

    Depuis la MAJ des scripts 18.02.09, il semblerait que le script PIN356ONOFFRESET n'accepte plus que des boutons PUSH, d'après ce post :
    https://forum.recalbox.com/topic/12678/mise-%C3%A0-jour-18-02-09-question-power-scripts

    Du moins, c'est ce que j'en déduis aussi d'après le comportement de mon ON/OFF.

    Quelqu'un peut confirmer SVP ?

    Merci d'avance


  • Moderator
    Team
    Creator
    Moderator

    @ff-sounds Bonjour,

    Effectivement comme le script gère les temps d'appuie, c'est difficile de faire fonctionner un ON/OFF.
    Malgré tout, il y a un pb évident que j'essaierai de corriger prochainement.

    En revanche, le comportement de ton reset n'est pas normal.

    durée/bouton sous ES En jeu
    RESET court rien reset du system (RetroArch only)
    RESET long reset propre du système reset propre du système
    POWER court rien quit du system et retour à ES
    POWER long shutdown propre du système reset propre du système


  • @supernature2k Bonjour,

    Merci d'avoir répondu :)

    Du coup, pour mon projet SNES, le script actuel n'est pas ce qu'il y a de mieux ;)
    Pour le Reset, il faut que je reteste, j'ai peut être pas bien assimilé les comportements attendu par le script, à voir !
    En tout cas, je n'avais pas précisé, mais la LED fonctionne bien, avec tout de même une petite coupure au chargement d'ES, mais ce n'est pas un problème.

    Pensez-vous qu'il serait possible de laisser le choix dans les scripts avec l'ancienne version du PIN356ONOFFRESET ?
    Ce que j'entends par là, c'est d'avoir au final 4 scripts au choix, qui pourraient couvrir le grande majorité des configs/mods, par exemple :

    • PIN56ONOFF
    • PIN56PUSH
    • PIN356ONOFFRESET (pour switch ON/OFF)
    • PIN356ONOFFRESETPUSH (pour l'actuel avec seulement des PUSH)

    Vous en pensez quoi ?
    Je ne pense pas être un cas isolé avec mon switch ON/OFF :D

    Sinon, est-ce que je peux abusé et demander le fichier ou le code avant gestion des temps d'appui ?
    Je le remplacerai à la main, et à chaque MAJ d'ailleurs ;)

    Merci d'avance !



  • @ff-sounds Effectivement tu n'es pas le seul dans ce cas la ^^
    Je bosse sur le même projet que toi, sauf que je n'ai pas encore testé le script des boutons ON/OFF et RESET et je suis comme toi preneur d'une solution pour composer avec le switch bistable ON/OFF et le momentané RESET ;)


  • Moderator
    Team
    Creator
    Moderator

    @ff-sounds can you please test dat shit: (tu remplaces le fichier rpi-pin356-power.py et dans recalbox.conf tu choisi system.power.switch=PIN356ONOFFRESET)

    import RPi.GPIO as GPIO
    import time
    import os
    import thread
    import datetime
    import socket
    import sys
    import argparse
    from datetime import datetime
    from configgen import recalboxFiles
    # this last one retrieves emulators bin names
    
    parser = argparse.ArgumentParser(description='power manager')
    parser.add_argument("-m", help="mode onoff or push", type=str, required=True)
    args = parser.parse_args()
    
    mode = args.m
    
    IPADDR = "127.0.0.1"
    PORTNUM = 55355
    # IP and port for retroarch network commands
    
    POWERPLUS = 3
    RESETPLUS = 2
    LED = 14
    
    GPIO.setwarnings(False)		# no warnings
    GPIO.setmode(GPIO.BCM)		# set up BCM GPIO numbering 
     
    GPIO.setup(RESETPLUS, GPIO.IN, pull_up_down=GPIO.PUD_UP)
    # GPIO on pin 3 is the GPIO 2 in BCM mode
    #to Reset+
    
    GPIO.setup(POWERPLUS, GPIO.IN, pull_up_down=GPIO.PUD_UP)
    # GPIO on pin 5 is the GPIO 3 in BCM mode
    #to Power+
    
    GPIO.setup(LED, GPIO.OUT)
    GPIO.output(LED, True)
    # GPIO on pin 8 is the GPIO 14 in BCM mode
    #to LED+
    
      
    # Define a threaded callback function to run in another thread when events are detected  
    def button_pressed(channel):
    	if channel == POWERPLUS:
    		speed=0.15
    		shutdownstring="shutdown -h now"
    		nwcommand="QUIT"
    		
    	elif channel == RESETPLUS:
    		speed=0.05
    		shutdownstring="shutdown -r now"
    		nwcommand="RESET"
    		
    	timer = 0
    	flag = True
    	while flag:
    		if GPIO.input(channel) == False:
    			timer += 1
    			print "Button pressed"
    		elif GPIO.input(channel) == True:
    		
    			print "Button released"
    			print timer
    		
    			#timer adds 1 each 0.1 seconds if timer = 10, button is pressed for 1s
    			if (timer > 10):
    				offreset(speed, shutdownstring)
    				print "shutdown"
    			elif (timer >1):
    				retroarch(nwcommand)
    				print "retroarch"
    				killthatshit(channel)
    				
    			timer = 0
    			flag = False
    		time.sleep(0.1)
    	
    def button_changed(channel):
    	if channel == POWERPLUS:
    		speed=0.15
    		shutdownstring="shutdown -h now"
    	
    	offreset(speed, shutdownstring)
    	
    #	on power short press, trying to kill all listed emus 
    def killthatshit(channel):
    	if channel == POWERPLUS:
    		for bin in recalboxFiles.recalboxBins:
    				print bin
    				proc = os.path.basename(bin)
    				print proc
    				os.system("killall -9 "+proc)
    
    # 	on long button press clean stop	of ES then shutdown -h or -r		
    def offreset(speed, shutdownstring):
    	thread.start_new_thread( blink, (speed, ))
    	flag=True
    	pids = [pid for pid in os.listdir('/proc') if pid.isdigit()]
    	os.system("/etc/init.d/S31emulationstation stop")
    	while flag:
    		flag = False
    		for pid in pids:
    				try:
    					print pid
    					commandpath = open(os.path.join('/proc', pid, 'cmdline'), 'rb').read()
    					if "emulationstation" in commandpath:
    						flag = True
    				except IOError:
    					continue
    	os.system(shutdownstring)
    
    # threaded blinking function for LED	
    def blink(speed):
    	while True:  
    			GPIO.output(LED, False)
    			time.sleep(speed)
    			GPIO.output(LED, True)
    			time.sleep(speed)
    
    
    # 	sending network command to retroarch (only exit and reset atm)		
    def retroarch(nwcommand):
    	try:
    		s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    	except socket.error:
    		print 'Failed to create socket'
    		sys.exit()
    	s.sendto(nwcommand, (IPADDR, PORTNUM))
    		
    if mode == "onoff" :
        GPIO.add_event_detect(POWERPLUS, GPIO.RISING, callback=button_changed, bouncetime=2)
    elif mode == "push":
        GPIO.add_event_detect(POWERPLUS, GPIO.BOTH, callback=button_pressed, bouncetime=2)
    
    GPIO.add_event_detect(RESETPLUS, GPIO.BOTH, callback=button_pressed, bouncetime=2)
    
    while True:
    	time.sleep(0.2)
    

    Si ça fonctionne, je le mettrai dans la prochaine release



  • @supernature2k

    T'as fait une petite erreur dans le nom de la nouvelle fonction button_changed, elle est nommée button_pressed comme l'autre ;)
    Après cette correction:

    • Avec un switch ON/OFF, ça fonctionne correctement
    • Avec un PUSH ON/OFF, le boot fonctionne correctement mais, une fois booté, il n'y que l'appui court qui est pris en compte, pas de timer visiblement, dès qu'on appui, shutdown propre direct... pas de reboot que ce soit en jeu ou sous ES

    Pour le RESET, il n'y a que le reset du system Retroarch en jeu qui ne fonctionne pas...

    Merci pour la modif en tout cas :)


  • Moderator
    Team
    Creator
    Moderator

    @ff-sounds J'avoue je viens de le faire à l'arrache du bureau... pas testé :)
    je vais éditer le post...

    Pour passer en momentary il faut du coup activer le :
    system.power.switch=PIN356PUSHRESET dans recalbox.conf (tu peux tester?)

    Pour le reset RA, c'est étrange, il a toujours fonctionné chez moi.

    Check le retroarchcustom.cfg et vérifie que tu as bien une ligne :

    network_cmd_enable = "true"



  • @supernature2k

    Haaaa mais je ne savais pas qu'il existait ce mode PIN356PUSHRESET !!
    D'où le if mode == "onoff"/elif mode == "push".... rolala...

    En effet, network_cmd_enable = "true" n'était pas dans retroarchcustom.cfg, à corriger dans la prochaine release, il ne doit pas y être initialement je pense, car jamais touché à retroarchcustom.cfg

    ça fonctionne bien avec l'ajout de la ligne en mode PIN356PUSHRESET et PIN356ONOFFRESET :)

    Je vais me pencher sur un script perso dans ce cas, avec:

    • switch ON/OFF classique
    • Reset court en jeu => reset du jeu
    • Reset long en jeu => retour ES
    • Reset court sous ES => reboot propre
    • Reset long sous ES => rien

    Je partagerai le code pour ceux que ça intéresseraient :) (c'est quoi la fonction pour mettre du code sur le forum ??)

    Merci beaucoup !


  • Moderator
    Team
    Creator
    Moderator

    @ff-sounds Pas bête cette idée de script, si tu y arrives fait une MR pour l'ajouter :)



  • @supernature2k

    Est ce que tu pourrais me dire comment identifier si Retroarch est en cours d'execution ?
    Le reset court et long en jeu c'est facile (et ça marche !), mais pour poser les conditions pour ES il faut que je sache si on est en jeu ou pas...
    Je ne sais pas comment faire du coup.
    Ma pratique du code (même pas Python en plus) remonte à 2002.. lol !

    Please help :)


  • Moderator
    Team
    Creator
    Moderator

    @ff-sounds Pour retroarch tu peux chercher si le pid existe (comme je le fais pour ES pour le clean shutdown).
    Par contre il y a les autres emulateurs standalone, là ça se complique



  • @supernature2k

    Salut !

    Bon alors après plein d'essais, ça ne fonctionne pas, y'a un truc que je pige pas, tant pis, je vais laisser le reset court/long en jeu, ça me va bien comme ça :)

    Comme tu dis, ça se complique pour les autres emus standalone, je me demande si il n'y a pas un moyen de savoir qui à la main en affichage, ce serait vite réglé !
    si pas ES on est en jeu, simplement :)

    A réfléchir !

    Merci pour le coup de main !


  • Themer

    @ff-sounds suffit de vérifier qu'il y a un processus avec 'emulatorlauncher.py' dans le titre de lancé par ps -ef | grep emulatorlauncher si oui tu es en cours d'exécution d'un emulateur, sinon dans ES



  • @voljega

    Oui c'est pas bête, mais je suis loin d'assurer à max en code !
    J'ai la logique mais pas tous les "mots" pour mettre en oeuvre, alors c'est plutôt embêtant :)

    Mais je vais y regarder, ça m’intéresse, ça prendra le temps que ça prendra, je demanderai peut être un coup de main ;)

    Merci pour ton aide !



  • @voljega @supernature2k

    Bonjour,

    J'ai besoin de vos lumières, j'ai testé tout un tas de chose, il me manque juste un truc, je n'arrive pas un récupéré une variable (present) pour la tester...

    Please help :)

    		elif (timer >1):
    			search_launcher(channel)
    				if present == True:
    					nwcommand="RESET"
    					retroarch(nwcommand)
    					print "retroarch"
    					killthatshit(channel)
    				else:	
    					speed=0.05
    					shutdownstring="shutdown -r now"
    					offreset(speed, shutdownstring)
    					print "reboot"
    		timer = 0
    		flag = False
    	time.sleep(0.1)
    	
    def search_launcher(channel):
    	if channel == RESETPLUS:
    		pids = [pid for pid in os.listdir('/proc') if pid.isdigit()]
    		for pid in pids:
    			try:
    				print pid
    				commandpath = open(os.path.join('/proc', pid, 'cmdline'), 'rb').read()
    				if "emulatorlauncher" in commandpath:
    					present = True
    			except IOError:
    				continue


  • def search_launcher(channel):
         if channel == RESETPLUS:
             proc = subprocess.Popen('ps -ef | grep emulatorlauncher', stdout=subprocess.PIPE)
             tmp = proc.stdout.read()
             if tmp:
                 present = true
             else:
                 present = false
    

    Pas sur du tout de mon coup, le python n'est pas un langage que je maitrise ^^
    Y'a même moyen de se passer de ta variable present et de tester le result renvoyé par search_launcher (à la place de present = true tu mets result = true, pareil pour false, et dans la première partie de ton code tu fais if search_launcher(channel) == true : etc...



  • 	elif (timer >1):
    			if search_launcher(channel) == True:
    				nwcommand="RESET"
    				retroarch(nwcommand)
    				print "retroarch"
    				killthatshit(channel)
    			else:	
    				speed=0.05
    				shutdownstring="shutdown -r now"
    				offreset(speed, shutdownstring)
    				print "reboot"
    	timer = 0
    	flag = False
    time.sleep(0.1)
    
    def search_launcher(channel):
        if channel == RESETPLUS:
    	proc=subprocess.Popen('ps -ef | grep emulatorlauncher', stdout=subprocess.PIPE)
            tmp=proc.stdout.read()
            if tmp:
                return True
            else:
                return False
    

    Un truc dans le genre, les cadors du .py seront plus à même de valider ma grouille ^^


  • Themer

    @neeeeb @FF-Sounds ouip ce que t'as dit neeeeb est plus simple et moins source d'erreur, je ne me souviens plus de la portée exacte des variables en python.

    autre possiblité, déclare juste ta varaible en haut de ton code en dehors de toute fonction, juste par present = False (après les imports tout de même)



  • Les variables globales c'est le mal ^^ j'essaye toujours de les éviter au maximum.



Want to support us ?

Join us on :

274
Online

28225
Users

14441
Topics

109280
Posts

Looks like your connection to Recalbox Forum was lost, please wait while we try to reconnect.