NES power switch on GPIO


  • Moderator
    Team
    Creator
    Moderator

    Hi All, Comme de nombreux avant moi, je suis en train de monter une racalbox dans un boitier NES. J'avais commandé un Mausberry switch pour gérer les boutons mais comme ils m'ont mis une carotte... Je me repli sur le mode GPIO que la team a implémenté il y a peu. Le problème, c'est que le script ne gère que le Power, pas le Reset. J'ai donc mis les mains dedans pour améliorer le script et gérer les deux actions (+ la LED). Les deux fichier à ajouter/écraser: rpi-nes.py

    import RPi.GPIO as GPIO
    import time
    import os
    
    POWERPLUS = 3
    RESETPLUS = 2
    LED = 14
    
    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+
    
    POWER_triggered = False
    RESET_triggered = False
    
    # Define a threaded callback function to run in another thread when events are detected  
    def reset(channel):
    	global RESET_triggered
    	RESET_triggered = True
    
    def power(channel):
    	global POWER_triggered
    	POWER_triggered = True
    
    def blink(speed):
    	GPIO.output(LED, False)
    	time.sleep(speed)
    	GPIO.output(LED, True)
    	time.sleep(speed)
    
    GPIO.add_event_detect(RESETPLUS, GPIO.FALLING, callback=reset)
    GPIO.add_event_detect(POWERPLUS, GPIO.RISING, callback=power)
    
    while not POWER_triggered and not RESET_triggered:
    	time.sleep(.1)
    
    if RESET_triggered:
    	os.system("shutdown -r now")
    	for i in range(0,100):  
    			blink(0.05)
    
    if POWER_triggered:
    	os.system("shutdown -h now")
    	for i in range(0,10):  
    			blink(0.15)
    
    GPIO.cleanup()         # clean up after yourself  
    

    powerswitch.sh

    #!/bin/bash
    
    # http://lowpowerlab.com/atxraspi/#installation
    atx_raspi_start()
    {
        # This is GPIO 7 (pin 26 on the pinout diagram).
        # This is an input from ATXRaspi to the Pi.
        # When button is held for ~3 seconds, this pin will become HIGH signalling to this script to poweroff the Pi.
        SHUTDOWN=$1
        REBOOTPULSEMINIMUM=200        #reboot pulse signal should be at least this long
        REBOOTPULSEMAXIMUM=600        #reboot pulse signal should be at most this long
        echo "$SHUTDOWN" > /sys/class/gpio/export
        echo "in" > /sys/class/gpio/gpio$SHUTDOWN/direction
    
        # Added reboot feature (with ATXRaspi R2.6 (or ATXRaspi 2.5 with blue dot on chip)
        # Hold ATXRaspi button for at least 500ms but no more than 2000ms and a reboot HIGH pulse of 500ms length will be issued
    
        # This is GPIO 8 (pin 24 on the pinout diagram).
        # This is an output from Pi to ATXRaspi and signals that the Pi has booted.
        # This pin is asserted HIGH as soon as this script runs (by writing "1" to /sys/class/gpio/gpio8/value)
        BOOT=$2
        echo "$BOOT" > /sys/class/gpio/export
        echo "out" > /sys/class/gpio/gpio$BOOT/direction
        echo "1" > /sys/class/gpio/gpio$BOOT/value
    
        echo "ATXRaspi shutdown script started: asserted pins ($SHUTDOWN=input,LOW; $BOOT=output,HIGH). Waiting for GPIO$SHUTDOWN to become HIGH..."
    
        #This loop continuously checks if the shutdown button was pressed on ATXRaspi (GPIO7 to become HIGH), and issues a shutdown when that happens.
        #It sleeps as long as that has not happened.
        while true; do
            shutdownSignal=$(cat /sys/class/gpio/gpio$SHUTDOWN/value)
            if [ $shutdownSignal = 0 ]; then
                /bin/sleep 0.2
            else
                pulseStart=$(date +%s%N | cut -b1-13) # mark the time when Shutoff signal went HIGH (milliseconds since epoch)
                while [ $shutdownSignal = 1 ]; do
                    /bin/sleep 0.02
                    if [ $(($(date +%s%N | cut -b1-13)-$pulseStart)) -gt $REBOOTPULSEMAXIMUM ]; then
                        echo "ATXRaspi triggered a shutdown signal, halting Rpi ... "
                        touch "/tmp/poweroff.please"
                        poweroff
                        exit
                    fi
                    shutdownSignal=$(cat /sys/class/gpio/gpio$SHUTDOWN/value)
                done
                #pulse went LOW, check if it was long enough, and trigger reboot
                if [ $(($(date +%s%N | cut -b1-13)-$pulseStart)) -gt $REBOOTPULSEMINIMUM ]; then 
                    echo "ATXRaspi triggered a reboot signal, recycling Rpi ... "
                    reboot
                    exit
                fi
            fi
        done    
    }
    
    atx_raspi_stop()
    {
        # Cleanup GPIO init
        for i in $*; do
            echo "$i" > /sys/class/gpio/unexport
        done
    }
    
    # http://mausberry-circuits.myshopify.com/pages/setup
    mausberry_start()
    {
        # Init GPIO :
        # $1 is the GPIO pin connected to the lead on switch labeled OUT
        # $2 is the GPIO pin connected to the lead on switch labeled IN
        echo "$1" > /sys/class/gpio/export
        echo "in" > /sys/class/gpio/gpio$1/direction
    
        echo "$2" > /sys/class/gpio/export
        echo "out" > /sys/class/gpio/gpio$2/direction
        echo "1" > /sys/class/gpio/gpio$2/value
    
        # Wait for switch off signal 
        power=0
        while [ "$power" = "0" ]; do
            sleep 1
            power=$(cat /sys/class/gpio/gpio$1/value)
        done
    
        # Switch off
        if [ "$?" = "0" ]; then
            touch "/tmp/poweroff.please"
            poweroff
        fi
    }
    
    mausberry_stop()
    {
        # Cleanup GPIO init
        for i in $*; do
            echo "$i" > /sys/class/gpio/unexport
        done
    }
    
    # http://www.msldigital.com/pages/support-for-remotepi-board-2013
    # http://www.msldigital.com/pages/support-for-remotepi-board-plus-2015
    msldigital_start()
    {
        # Init GPIO : 
        # $1 is the GPIO pin receiving the shut-down signal
        echo "$1" > /sys/class/gpio/export
        echo "in" > /sys/class/gpio/gpio$1/direction
    
        # Wait for switch off signal 
        power=0
        while [ "$power" = "0" ]; do
            sleep 1
            power=$(cat /sys/class/gpio/gpio$1/value)
        done
    
        # Switch off
        if [ "$?" = "0" ]; then
            touch "/tmp/poweroff.please"
            poweroff
        fi
    }
    
    msldigital_stop()
    {
        if [ -f "/tmp/shutdown.please" -o -f "/tmp/poweroff.please" ]; then
            if [ -f "/tmp/shutdown.please" -a "$CONFVALUE" = "REMOTEPIBOARD_2005" ]; then
                # Init GPIO
                GPIOpin=15
                echo "$GPIOpin" > /sys/class/gpio/export
    
                # Execute shutdown sequence on pin
                echo "out" > /sys/class/gpio/gpio$GPIOpin/direction
                echo "1" > /sys/class/gpio/gpio$GPIOpin/value
                usleep 125000
                echo "0" > /sys/class/gpio/gpio$GPIOpin/value
                usleep 200000
                echo "1" > /sys/class/gpio/gpio$GPIOpin/value
                usleep 400000
                echo "0" > /sys/class/gpio/gpio$GPIOpin/value
                sleep 1
    
                # Uninit GPIO
                echo "$GPIOpin" > /sys/class/gpio/unexport
            fi
            echo "out" > /sys/class/gpio/gpio$1/direction
            echo "1" > /sys/class/gpio/gpio$1/value
            sleep 3
        fi
        # Cleanup GPIO init
        for i in $*; do
            echo "$i" > /sys/class/gpio/unexport
        done
    }
    
    nes_start()
    {
    	python /recalbox/scripts/rpi-nes.py &
        pid=$!
        echo "$pid" > /tmp/rpi-nes.pid
        wait "$pid"
    }
    nes_stop()
    {
        if [[ -f /tmp/rpi-nes.pid ]]; then
            kill <code>cat /tmp/rpi-nes.pid</code>
        fi
    }
    
    pin56_start()
    {
        mode=$1
        python /recalbox/scripts/rpi-pin56-power.py -m "$mode" &
        pid=$!
        echo "$pid" > /tmp/rpi-pin56-power.pid
        wait "$pid"
    }
    pin56_stop()
    {
        if [[ -f /tmp/rpi-pin56-power.pid ]]; then
            kill <code>cat /tmp/rpi-pin56-power.pid</code>
        fi
    }
    
    # First parameter must be start or stop
    if [[ "$1" != "start" && $1 != "stop" ]]; then
        exit 1
    fi
    
    CONFFILE="/recalbox/share/system/recalbox.conf"
    CONFPARAM="system.power.switch" 
    CONFVALUE=
    if [ -e $CONFFILE ]; then
        CONFVALUE=$(sed -rn "s/^$CONFPARAM=(\w*)\s*.*$/\1/p" $CONFFILE | tail -n 1)
    fi
    
    case "$CONFVALUE" in
        "ATX_RASPI_R2_6")
            atx_raspi_$1 7 8
        ;;
        "MAUSBERRY")
            mausberry_$1 23 24
        ;;
        "REMOTEPIBOARD_2003")
            msldigital_$1 22
        ;;
        "REMOTEPIBOARD_2005")
            msldigital_$1 14
        ;;
        "PIN56ONOFF")
            pin56_$1 onoff
        ;;
        "PIN56PUSH")
            echo "will start pin56_$1"
            pin56_$1 push
        ;;
    	"NES")
            echo "will start NES_$1"
            nes_$1 useless
        ;;
    esac
    

    -SSH sur la recalbox -mount -o remount, rw / pour passer la partition en écriture -copie des 2 fichiers dans /recalbox/scripts -modif des droits: chmod 644 rpi-nes.py et chmod 755 powerswitch.sh -enfin, on ajoute system.power.switch=NES dans le recalbox.conf Maintenant pour ce qui est du câbage: -Power+ (Fil marron) --> GPIO3 (pin 5) -Reset+ (Fil jaune)--> GPIO2 (pin 3) -LED+ --> GPIO14 (pin 8) -Power- (Fil rouge), Reset- (Fil orange), LED- --> GND (pin 6) Ne pas oublier de mettre une resistance de 300 Ohm sur le LED+ Pour la LED, soit on vient souder 2 fils dessus et on coupe la trace du PCB qui va au Reset- Ou bien on retourne la LED sur le PCB et dans ce cas le fil Reset- est aussi la masse de la LED. Une fois tout ça en place, vous aurez un bouton Power qui allume et éteind la Recalbox et un bouton Reset qui la redémarre (soft reset). En prime, j'ai rajouté du clignotement de LED dans le script (rapide pour reset, lent pour power).



  • salut, j'aimerais juste branché mon bouton reset de la nes pour pouvoir revenir au menu en cours de jeux (hotkey + start). comment procédé? merci de vos réponse


  • Moderator
    Team
    Creator
    Moderator

    Hi, Je ne sais pas exactement mais regarde ici. Pour le bouton reset de la NES: fil jaune= reset + (à mettre sur le GPIO correspondant à keyb_esc) et fil orange= reset - (à mettre sur un des GPIO ground).



  • Salut, est ce que tu peux envoie des images du GPIO avec le bon couleur? STP j'arrive a faire marche le reset mais le power ca fair rien :-( Merci


  • Moderator
    Team
    Creator
    Moderator

    Hi @aldo_ferrari, Tu peux trouver une image des GPIO ici: Wiki Pour les branchements: -Power+ –> GPIO3 (pin 5) -Reset+ –> GPIO2 (pin 3) -LED+ –> GPIO14 (pin 8) -Power- , Reset- , LED- –> GND (pin 6) Pour info, il y a depuis une version améliorée du script. Elle sera intégré à la prochaine version de Recalbox.



  • did the code change with the new beta 4 released?


  • Moderator
    Team
    Creator
    Moderator

    Hi @aldo_ferrari, Yes the code changed since it has been included in the latest release. Unfotunately I can't edit the first post of this topic.



  • could you re-post it? :-)


  • Moderator
    Team
    Creator
    Moderator

    you can find it here: github



  • Bonjour, Peut on transposer ce montage sur le GPIO du Raspberry Pi 2 ? Merci


  • Moderator
    Team
    Creator
    Moderator

    Bonjour @tong-man, Oui le rpi2 a les mêmes GPIO que le rpi3. Et comme le script utilise les pin 3 5 6 et 8, ça devrait même fonctionner sur un rpi1.



  • Salut @supernature2k, Quand tu dis pin 3 5 6 et 8, tu parles des GPIO ou des pinoches. Je viens de lister les pin du gpio du rpi2, les pin 3 5 6 et 8 correspondent respectivement au SDA.1, SCL.1, 0V et ALT0. Pour l'obtenir en ssh, j'ai tapé la commande : gpio readall l'interface GPIO du rpi2 et 3 sont sans doutes les mêmes mais pas celle du rpi1 (moins de pin) maintenant, si le script nomme bien les gpio, la correspondance avec les pins se fera automatiquement pour le gpio du rpi2 et 3 et sera la suivante: -Power+ –> GPIO3 (pin 15) -Reset+ –> GPIO2 (pin 13) -LED+ –> GPIO14 n'existe pas (pin ???) à moins que ce soit le GPIO4 = pin 16. -Power- , Reset- , LED- –> GND (pin 9, 25, 39, 14, 20, 30 ou 34) En tout cas merci pour ta réponse.   autre info qui peut avoir son importance, les GPIO en mode sortie sur le rpi2 fournissent du 3.3V et en mode entrée attendent du 3.3V et non du 5V. Dans le script, le power+ attend du 3.3V ou du 0V ?


  • Moderator
    Team
    Creator
    Moderator

    Bonjour @tong-man, Quand je dis pin 3 5 6 8 je parles... des pins :) Donc: Power+ pin 5 GPIO 3 Reset+ pin 3 GPIO 2 LED+ pin 8 GPIO 14 tous les -, n'importe quel GND (pin 6 le plus facile) Dans le script, j'utilise: GPIO.setmode(GPIO.BCM) # set up BCM GPIO numbering Ce qui veut dire que j'utilise la numérotation GPIO et non PIN. Cela implique que ça ne doit pas fonctionner avec Raspberry Pi B rev 1 P1 comme montré ici: GPIO On y voit en effet que sur ce modèle, les pin 3 et 5 correspondent aux GPIO 0 et 1. Pour tous les autres pi, aucun problème. Plus d'infos ici: wiki Enfin pour l'histoire du voltage, ça n'a aucune influence sur le bouton. Le script détecte une montée de voltage sur le GPIO lorsque le circuit est fermé, c'est tout.



  • Salut @Supernature2k<b></b><i></i><u></u> Ok si tu as utilisé le nommage des GPIO, cela devrait effectivement fonctionner sur le gpio du rpi2 A ceci prêt qu'il faut que j'utilise les pins : Power+ –> GPIO3 (pin 15) -Reset+ –> GPIO2 (pin 13) -LED+ –> GPIO14 n’existe pas (pin ???) -Power- , Reset- , LED- –> GND (pin 9, 25, 39, 14, 20, 30 ou 34 Voici le tableau de correspondance du gpio 40 broches du rpi2 : (désolé pour le copier coller un peu foireux) Il faut regarder les physical (pin) et les gpio. pi@raspberrypi:~ $ gpio readall +-----+-----+---------+------+---+---Pi 2---+---+------+---------+-----+-----+ | BCM| wPi | Name   |Mode| V | Physical  | V | Mode | Name    | wPi | BCM | +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+ |         |         |    3.3v    |          |      |  1   | | 2    |      |          | 5v           |         |         | |   2    |   8   |   SDA.1 |   IN   | 1   |  3   | | 4   |       |          | 5V          |         |         | |   3    |   9   |   SCL.1  |   IN   | 1   |  5   | | 6    |      |          | 0v           |         |        | |   4    |   7   | GPIO. 7 |   IN  | 1   |  7    | | 8   | 1   | ALT0 | TxD     | 15     | 14   | |         |        |      0v      |          |      |  9   | | 10  | 1   | ALT0 | RxD     | 16  | 15  | |  17   |   0  | GPIO. 0 |  OUT | 1  | 11   || 12  | 0 | IN        | GPIO. 1 | 1   | 18  | |  27  |   2  | GPIO. 2 |  OUT  | 1  | 13  || 14   |    |              | 0v           |      |     | |  22  |   3  | GPIO. 3 |  OUT | 1   | 15  || 16   | 0 | IN        | GPIO. 4 | 4   | 23  | |         |       |    3.3v      |           |      | 17 || 18   | 1  | OUT    | GPIO. 5 | 5   | 24  | |  10  |  12  |    MOSI   |   IN   | 0  | 19 || 20   |    |              | 0v            |     |     | |   9   |  13 |    MISO      |   IN | 0 | 21 || 22     | 0 | IN       | GPIO. 6 | 6   | 25  | |  11  |  14  |    SCLK      |   IN | 0 | 23 || 24     | 1 | IN       | CE0        | 10  | 8   | |        |       |      0v           |        |    |  25 || 26     | 1  | IN       | CE1         | 11   | 7   | |   0  |  30 |   SDA.0      |   IN | 1 | 27 || 28      | 1  | IN      |  SCL.0    |  31  | 1   | |   5 |  21   | GPIO.21    |   IN | 1 | 29 || 30 |   |      | 0v      |     |     | |   6 |  22 | GPIO.22 |   IN    | 1   | 31 || 32 | 0 | IN   | GPIO.26 | 26  | 12  | |  13 |  23 | GPIO.23 |   IN | 0  | 33 || 34 |   |        | 0v               |        |       | |  19 |  24 | GPIO.24 |   IN | 0  |  35 || 36 | 0 | IN   | GPIO.27 | 27  | 16  | |  26 |  25 | GPIO.25 |   IN | 0  | 37 || 38 | 0 | IN   | GPIO.28 | 28  | 20  | |        |       |      0v           |      |    | 39 || 40 | 0 | IN   | GPIO.29 | 29  | 21  | Comme tu peux le constater le gpio 14 n'existe pas sur le rpi2, bref pour le moment je n'ai pas besoin de bouton reset et au pire je modifierai le script en conséquence pour en utiliser un autre. N'hesites pas à me corriger si je dis une bétise, mais il me semble que celui que tu présentes est bien celui du Raspberry Pi B rev 1 P1 et il n'a pas 40 broches. de plus, j'utilise aussi un autre rpi2 sur un tout autre domaine (alarme domicile) et j'utilise aussi l'interface de son gpio, notamment, les gpio 0, 2, 3,4, 5 et 6, le 5V et les 2 3.3V, qui aliments une carte 4 relais .... <b></b><i></i><u></u> Ceci dit, je pense que je vais tester pour avoir la réponse définitive et te tient au courant, Bonne soirée.


  • Moderator
    Team
    Creator
    Moderator

    @tong-man, Je ne sais pas d'où sort ce tableau mais regarde le lien que j'ai fourni précédemment, à 26 ou 40 broches, on a bien le GPIO14 qui est sur le Pin 8. On a aussi toujours le pin 6 qui est un GND. Enfin, en 26 broches rev2 et en 40 broches, on a bien GPIO2 et GPIO3 en pin 5 et 6 donc aucun problème. Regarde bien ton tableau illisible:

    | BCM    | wPi   | Name    |Mode    | V   | Physical     | V | Mode | Name    | wPi | BCM |
    
    |   2    |   8   |   SDA.1 |   IN   | 1   |  3   | | 4   |   |      | 5V      |     |     |
    |   3    |   9   |   SCL.1 |   IN   | 1   |  5   | | 6   |   |      | 0v      |     |     |
    |   4    |   7   | GPIO. 7 |   IN   | 1   |  7   | | 8   | 1 | ALT0 | TxD     | 15  | 14  |
    

    Il dit la même chose que moi... Dernière ligne, physical 8, BCM 14...



  • Salut, Mon tableau est obtenu en tapant la commande ssh gpio readall directement sur mon raspberry pi2 : Il correspond au tableau dessiné sur ce site: http://pi4j.com/pins/model-2b-rev1.html je possède le "Raspberry Pi 2 Model B" D'ou mes interrogations. donc pour ce pi2, power+ sur gpio 2 = pin 13 reset+ sur gpio 3 = pin 15 led+ sur gpio 14 = pin 23 gnd = au choix pin 9 soir 2 pin au dessus de power+ pin 13 Ainsi cela devrait fonctionner :) Etant parti en vacances , je confirmerai ça dés mon retour début Aout. Merci encore pour tes différentes explications et réponses.


  • Moderator
    Team
    Creator
    Moderator

    Non @tong-man, Encore une fois, relis ton 1er tableau et tu verras que la numérotation est la même: | BCM | wPi | Name |Mode | V | Physical | V | Mode | Name | wPi | BCM | | 2 | 8 | SDA.1 | IN | 1 | 3 | | 4 | | | 5V | | | | 3 | 9 | SCL.1 | IN | 1 | 5 | | 6 | | | 0v | | | | 4 | 7 | GPIO. 7 | IN | 1 | 7 | | 8 | 1 | ALT0 | TxD | 15 | 14 | Regarde en bas du tableau que tu as mis en lien: Attention! The GPIO pin numbering used in this diagram is intended for use with WiringPi / Pi4J. This pin numbering is not the rw Broadcom GPIO pin numbers.



  • Bonjour @supernature2k !

    Je suis rentré de vacance et me donc atelé à intégrer un pi2 dans une NES.

    Pour commencer, oui j'avais tord et tu avais raison. j'avais pas percuté que tu utilisais le nommage BCM et non GPIO, ce qui ne donne pas du tout les mêmes numéros de pin.

    Alors, le PCB de la NES comprenant le POWER, le RESET et la LED fonctionne très bien à un détail prés : Le boutons POWER fonctionne à l'envers : lorsqu'il est appuyé, recalbox s'éteint
    et lorsqu'il est relaché, recalbox s'allume... Je me demande si ce n'est pas un bouton qui ouvre le circuit lorsqu'il est appuyé, je vérifierai cela lorsque j'aurai récupérer mon multimètre.

    power+ (pin 5)
    reset+ (pin 3)
    Led+ (pin 8)
    GND pour tous (pin 6)
    un sucre 4 ports entre les fils du PCB de la NES et le GPIO du rpi2 et le tour est joué.

    A moins que j'ai fait une erreur quelques part ?

    Autrement le tuto est très clair et dans recalbox.conf, j'ai ajouté la ligne :
    system.power.switch=PIN356ONOFFRESET
    comme indiqué ici :
    https://github.com/recalbox/recalbox-os/wiki/Add-a-start-stop-button-to-your-recalbox-(EN)
    la commande system.power.switch=NES est inopérente.

    @+ et merci
    Seb


  • Moderator
    Team
    Creator
    Moderator

    Effectivement, le script est désormais intégré a recalbox sous le nom pin356onoffreset.

    Pour le bouton power, essaie de le transformer en momentary.



  • Merci pour la soluce ;)

    Je confirme que le bouton Power de la NES ferme le circuit lorsqu'il est retiré et l'ouvre lorsqu'il est appuyé, d'où l'inversion de la fonction ON OFF sur la recalbox.

    Je le transformerai en momentary , pour le moment c'est pas trop génant comme on dit ça fait le job ;)

    Seb


Log in to reply
 

Want to support us ?

Join us on :

394
Online

31156
Users

15125
Topics

113811
Posts

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