Emulator Exit button GPIO



  • I was curious as to modify an existing script to work from retropie to RecalBox. I've got a button wired up to a GPIO pin to exit out of all the emulators on RetroPie 3.8 and on 4.0 Beta. However when I try to use the same script in RecalBox I can see the button output on the terminal screen when pressed. I've used this in the event the emulator freezes up and hotkeys don't work, I can still get back to emulation station.
    from time import sleep

    import os
    import RPi.GPIO as GPIO
    
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(17, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
    
    def exitEmulator(channel):
        print('exitEmulator')
        pids = [pid for pid in os.listdir('/proc') if pid.isdigit()]
    
        for pid in pids:
            try:
                commandpath = open(os.path.join('/proc', pid, 'cmdline'), 'rb').read()
                if commandpath[0:24] == '/opt/retropie/emulators/':
                    os.system('kill -QUIT %s' % pid)
                    print('kill -QUIT %s' % pid)
            except IOError:
                continue
    GPIO.add_event_detect(17, GPIO.RISING, callback=exitEmulator, bouncetime=500)
    
    while True:
        sleep(10)
    

    Thanks

    Here


  • Moderator
    Team

    Hey !

    That script is great :) your should edit your post to better handle syntax coloring ;)

    The path /opt/retropie/emulators doesn't exist on recalbox. All emulators are stored in /usr/bin, and I wouldt recommend you look for that path. The number of emulators is quite limited : retroarch, mupen64plus, moonlight, scummvm ... Tht.s the ones i can think of right now. I think they are listed in recalboxFiles.py in our configgen python package


  • Moderator
    Team
    Creator
    Moderator

    Sleep 10?



  • Yeah, I've copied and pasted it from a Reddit thread. Here is where I got it from.
    https://www.reddit.com/r/raspberry_pi/comments/2yw4fn/finally_set_up_retropie_complete_with_a_gpio/

    I really like the look and feel of RecalBox and wanted to use it in my other pi but had a few hiccups a long the way. One of them being this emulator exit button that I cannot get working on RecalBox. I think the other was the SNES GPIO adapter which I have kind of figured out.


  • Moderator
    Team

    The script is not that hard to adapt :

    • list binaries that one wants to shutdown. So far, there is moonlight, retroarch, fba2x, kodilauncher.sh, mupen64plus, scummvm
    • instead of getting cmdline, get exe (it's a symbolic link)
    • check that exe is among the listed binaries. If so, kill the pid

    One could make that script way more dirty : just throw a kill of all known processes, anyway only one of them is supposed to run at once

    The next recalbox version will add those binaries : dosbox, PPSSPPSDL, reicast.elf, linapple, x64

    What's your knowledge of python ?



  • My knowledge of Python is pretty much nil. I haven't had any real coding background whatsoever. I've tinkered and modified some stuff ini files for the original xbox to help automate flashing bios and setting up hard drives the way I like it. But that's really it. I usually take other peoples code and modify it to suit my needs. I would like to go back to college someday to learn about coding. Thanks for the input.


  • Moderator
    Team

    very lazy, didn't even try it :

    import os
    import RPi.GPIO as GPIO
    
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(17, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
    
    def exitEmulator(channel):
        print('exitEmulator')
        os.system('killall retroarch')
        
    GPIO.add_event_detect(17, GPIO.RISING, callback=exitEmulator, bouncetime=500)
    
    while True:
        sleep(10)
    

    that can work, only for retroarch for now

    you should start this file from a custom.sh located at /recalbox/share/system (you need to create it). Create it yourself add python yourfile.py inside, chmod u+x custom.sh and reboot



  • Thanks, I'll try it in a bit.


  • Moderator
    Team
    Creator
    Moderator

    I think import time is needed for the sleep function.
    Also, I would do it the other way for button press: GPIO.PUD_UP and GPIO.FALLING

    the code:

    import os
    import RPi.GPIO as GPIO
    import time
    
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(17, GPIO.IN, pull_up_down=GPIO.PUD_UP)
    
    def exitEmulator(channel):
        print('exitEmulator')
        os.system('killall retroarch')
        
    GPIO.add_event_detect(17, GPIO.FALLING, callback=exitEmulator, bouncetime=500)
    
    while True:
        sleep(10)
    

  • Moderator
    Team
    Creator
    Moderator

    Ok Guys, I made some test.

    I put a cable on Pin5 and pin6 and run the following code:

    import os
    import RPi.GPIO as GPIO
    import time
    
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(3, GPIO.IN, pull_up_down=GPIO.PUD_UP)
    
    def exitEmulator(channel):
        print("exitEmulator")
        os.system("killall retroarch")
        
    GPIO.add_event_detect(3, GPIO.FALLING, callback=exitEmulator, bouncetime=500)
    
    while True:
        time.sleep(10)
    

    And... it's working :)

    Of course in this current state, it's only working with retroarch emulators


  • Moderator
    Team

    haha i'm the man :D

    Seriously, most of emulators are listed in the recalboxFiles.py. Would need to improve it because all bins are not listed there. But I really like this idea : kill the running emulator, or even reset the game (there is a topic on it somewhere, will gid this and update my post) -> https://forum.recalbox.com/topic/3435/game-reset/6


  • Moderator
    Team
    Creator
    Moderator

    solution via python with network commands:

    import os
    import RPi.GPIO as GPIO
    import time
    import socket
    import sys
    # addressing information of target
    IPADDR = "127.0.0.1"
    PORTNUM = 55355
     
    # enter the data content of the UDP packet
    PACKETDATA = "RESET"
     
    # initialize a socket, think of it as a cable
    # SOCK_DGRAM specifies that this is UDP
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    except socket.error:
        print 'Failed to create socket'
        sys.exit()
    #s.connect((IPADDR, PORTNUM))
     
    # connect the socket, think of it as connecting the cable to the address location
    
    data = bytes(PACKETDATA)
    
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(3, GPIO.IN, pull_up_down=GPIO.PUD_UP)
    
    def exitEmulator(channel):
    	print("exitEmulator")
    	print(IPADDR)
    	print(PORTNUM)
    	print(PACKETDATA)
    	s.sendto(PACKETDATA, (IPADDR, PORTNUM))
        
    GPIO.add_event_detect(3, GPIO.FALLING, callback=exitEmulator, bouncetime=500)
    
    while True:
        time.sleep(10)
    

  • Moderator
    Moderator
    Team

    @supernature2k Hi,

    I'm replying to this old topic because I'm currently working on a project that needs such a feature. I tried your last script, I just removed GPIO code at for now to test, so here is my code:

    import os
    import time
    import socket
    import sys
    # addressing information of target
    IPADDR = "127.0.0.1"
    PORTNUM = 55355
    
    # enter the data content of the UDP packet
    PACKETDATA = "RESET"
    
    # initialize a socket, think of it as a cable
    # SOCK_DGRAM specifies that this is UDP
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    except socket.error:
        print 'Failed to create socket'
        sys.exit()
    #s.connect((IPADDR, PORTNUM))
    
    # connect the socket, think of it as connecting the cable to the address location
    
    data = bytes(PACKETDATA)
    
    print("exitEmulator")
    print(IPADDR)
    print(PORTNUM)
    print(PACKETDATA)
    s.sendto(PACKETDATA, (IPADDR, PORTNUM))
    

    So to try it, I start a retroarch game then I launch the script:

    # python rpi-exit-emulator.py 
    exitEmulator
    127.0.0.1
    55355
    RESET
    

    But in fact it does nothing, I'm still in the game (with no reset). Any idea ? :)


  • Moderator
    Team

    @oyyodams it's RESET, not exit ;)


  • Moderator
    Moderator
    Team

    @substring yes that's it's supposed to do... but no reset by the way...


  • Moderator
    Team

    @oyyodams check on command line if you can connect to the port ;) some netcat commands should do it


  • Moderator
    Moderator
    Team

    @substring Well I found a great doc on the wiki. But...

    • I can't use netcast: nc is not include in this buildroot build (and I can't rebuild by now)
    • It seems retroarch doesn't respond to any command. I tried to edit retroarch.cfg to add network_cmd_enable = "true", nothing better (even after reboot)

    I will not let go;)


  • Moderator
    Team

    @oyyodams hold the door !!!


  • Moderator
    Moderator
    Team

    @substring Hodor

    Don't worry I keep up the good work, things begin to be better, news soon ;)


  • Moderator
    Moderator
    Team

    Ok solution:

    network_cmd_enable = "true" has to be added in /recalbox/share/system/configs/retroarch/retroarchcustom.cfg


Log in to reply
 

Want to support us ?

Join us on :

266
Online

26893
Users

13866
Topics

105433
Posts

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