Mini Game Center -3-
Par makoto doushite le samedi, 11 janvier 2020, 10:16 - Raspberry Pi - Lien permanent
Suite de l'étude précédente :
Bien ! Maintenant que le système est installé, il nous faut un programme pour exploiter la mini-borne, et ainsi automatiser l'affichage des vidéos.
1 - Playlist de vidéos et pilotage par GPIO :
- Il faut voir mes petites bornes comme des judebox à jeux vidéos, qui jouent une vidéo en boucle.
- Sur la carte SD sont stockées plusieurs vidéos de démo de jeux ou de parties enregistrées.
- Les vidéos sont jouées par un script Python, et il est alors possible d'interagir avec la vidéo qui joue. Ainsi on va pouvoir :
- augmenter/diminuer le volume sonore, à l'aide de deux boutons poussoir.
- augmenter/diminuer la luminosité de l'écran, à l'aide de ces même deux boutons, avec un appuie long (> 2s).
- sauter de 30 secondes en avant/arrière, à l'aide de deux autres boutons poussoir.
- jouer la vidéo suivante/précédente, à l'aide de ces même de deux autres boutons, avec un appuie long (> 2s).
- faire une pause/relancer la lecture de la vidéo, à l'aide du bouton dédié.
- Voici dores et déjà une petite vidéo de démonstration pour bien comprendre l'idée :
- Et donc, pour ce faire, voici le schéma de câblage des boutons aux GPIO :
C'est le dessin du RaspberryPi Zero qui est représenté, mais les câbles (cf. la vidéo) sont bien raccordés sur le Pi HAT (cf. le schéma structurel). Les condensateurs d'anti-rebond font 100nF.
Il ne reste plus qu'a programmer…
- On a donc besoin de Python3 avec la librairie RPI.GPIO, et de la librairie omxcontrol de Douglas6 qui fonctionne avec dbus :
sudo apt-get install python3-rpi.gpio python3-dbus cd /home/pi git clone https://github.com/Douglas6/omxcontrol.git cd omxcontrol sudo python setup.py install
On a donc un dossier /home/pi/omxcontrol dans lequel on va placer notre programme Python pompeusement appelé « VideoOMXcontrol_GPIO_Multionctions_Playlist.py ».
#!/usr/bin/env python2.7 # coding: utf-8 # Compatible Python3 # Programme pour RaspberryPi # Joue une playliste de vidéos avec omxplayer # Pilotage des vidéos et de la playliste avec 5 boutons GPIO ################################## # Import des modules nécessaires # ################################## from omxcontrol import * import subprocess import RPi.GPIO as GPIO import time ############# # Init GPIO # ############# PIN_PLAY = 31 # GPIO06, Play/Pause/Stop [Appuie court et long] PIN_VOLMOINS = 35 # GPIO19, Volume - PIN_VOLPLUS = 37 # GPIO26, Volume + PIN_PRECEDENT = 38 # GPIO20, Précédent [Appuie court et long] PIN_SUIVANT = 36 # GPIO16, Suivant [Appuie court et long] PIN_BRIGHTNESS = 12 # GPIO18, PWM de réglage de la luminosité GPIO.setmode(GPIO.BOARD) ## Use board pin numbering GPIO.setup(PIN_PLAY, GPIO.IN, pull_up_down=GPIO.PUD_UP) GPIO.setup(PIN_VOLMOINS, GPIO.IN, pull_up_down=GPIO.PUD_UP) GPIO.setup(PIN_VOLPLUS, GPIO.IN, pull_up_down=GPIO.PUD_UP) GPIO.setup(PIN_PRECEDENT, GPIO.IN, pull_up_down=GPIO.PUD_UP) GPIO.setup(PIN_SUIVANT, GPIO.IN, pull_up_down=GPIO.PUD_UP) GPIO.setup(PIN_BRIGHTNESS, GPIO.OUT) ##################### # Ressources Vidéos # ##################### def Selection(i): switcher={ 0:'/home/pi/deathsml_15-07-2015_1cc_h264-21.mp4', 1:'/home/pi/dodonpachi_23-02-2014_montage.mp4', 2:'/home/pi/espgal_26-02-2015_1cc_x264_crf23.mp4', 3:'/home/pi/galaxian.mp4', } return switcher.get(i,"Séléction Invalide") ############# # Variables # ############# vid = 0 long_press = 1 very_long_press = 3 start = 0 end = 0 brightness = 100 pwm = GPIO.PWM(PIN_BRIGHTNESS, 130) # channel et frequence en Hz, meilleur résultat à 120 et 130Hz ############# # Démarrage # ############# os.system('sudo pkill omxplayer') # S'assure qu'aucune instance omxplayer ne tourne encore, en cas de plantage # omxplayer /home/pi/deathsml_15-07-2015_1cc_h264-21.mp4 --aspect-mode stretch -o local pwm.start(brightness) # Démarrage de la PWM du rétroéclairage LCD au max (100) # fonction qui sera appelée quand on appuiera sur le bouton : PIN_VOLMOINS def bouton_PIN_VOLMOINS(channel): global brightness global start global end if GPIO.input(channel) == GPIO.LOW: print("GPIO.LOW") start = time.time() if GPIO.input(channel) == GPIO.HIGH: print("GPIO.HIGH") end = time.time() elapsed = end - start print(elapsed) if (elapsed > very_long_press): print("very_long_press: ",very_long_press) # À DÉFINIR print('Fonction à définir') elif (elapsed > long_press): print("long_press :",long_press) # Baisser la luminosité de l'écran LCD brightness = brightness - 10 if brightness <= 10: brightness = 10 print("Luminosité baissée au max") print("Baisse la luminosite :", brightness) pwm.ChangeDutyCycle(brightness) elif (elapsed > 0): print("short_press") # Baisser le Volume du son print("Button Volume - pressé") omx.action(OmxControl.ACTION_DECREASE_VOLUME) def bouton_PIN_VOLPLUS(channel): global brightness global start global end if GPIO.input(channel) == GPIO.LOW: print("GPIO.LOW") start = time.time() if GPIO.input(channel) == GPIO.HIGH: print("GPIO.HIGH") end = time.time() elapsed = end - start print(elapsed) if (elapsed > very_long_press): print("very_long_press: ",very_long_press) # À DÉFINIR print('Fonction à définir') elif (elapsed > long_press): print("long_press :",long_press) # Augmenter la luminosité de l'écran LCD brightness = brightness + 10 if brightness >= 100: brightness = 100 print("Luminosité augmentée au max") print("Augmente la luminosite :", brightness) pwm.ChangeDutyCycle(brightness) elif (elapsed > 0): print("short_press") # Monter le Volume du son print("Button Volume + pressé") omx.action(OmxControl.ACTION_INCREASE_VOLUME) def bouton_PIN_PRECEDENT(channel): global vid global start global end if GPIO.input(channel) == GPIO.LOW: print("GPIO.LOW") start = time.time() if GPIO.input(channel) == GPIO.HIGH: print("GPIO.HIGH") end = time.time() elapsed = end - start print(elapsed) if (elapsed > very_long_press): print("very_long_press: ",very_long_press) # À DÉFINIR print('Fonction à définir') elif (elapsed > long_press): print("long_press :",long_press) # Stopper la lecture et tombe donc en erreur via Try > Except de la boucle principale print('Vidéo Précédente') omx.action(OmxControl.ACTION_EXIT) vid = vid - 1 # pour lire la vidéo précédente if vid == -1: vid = 3 print('vid : ',vid) elif (elapsed > 0): print("short_press") # un petit saut un arriére dans la vidéo print('<<') omx.action(OmxControl.ACTION_SEEK_BACK_SMALL) def bouton_PIN_SUIVANT(channel): global vid global start global end if GPIO.input(channel) == GPIO.LOW: print("GPIO.LOW") start = time.time() if GPIO.input(channel) == GPIO.HIGH: print("GPIO.HIGH") end = time.time() elapsed = end - start print(elapsed) if (elapsed > very_long_press): print("very_long_press: ",very_long_press) # À DÉFINIR print('Fonction à définir') elif (elapsed > long_press): print("long_press :",long_press) # Stopper la lecture et tombe donc en erreur via Try > Except de la boucle principale print('Vidéo Suivante') omx.action(OmxControl.ACTION_EXIT) vid = vid + 1 # pour lire la vidéo suivante if vid == 4: vid = 0 print('vid : ',vid) elif (elapsed > 0): print("short_press") # un petit saut en avant dans la vidéo print('>>') omx.action(OmxControl.ACTION_SEEK_FORWARD_SMALL) def bouton_PIN_PLAY(channel): global start global end if GPIO.input(channel) == GPIO.LOW: print("GPIO.LOW") start = time.time() if GPIO.input(channel) == GPIO.HIGH: print("GPIO.HIGH") end = time.time() elapsed = end - start print(elapsed) if (elapsed > very_long_press): print("very_long_press: ",very_long_press) # À DÉFINIR print('Fonction à définir') elif (elapsed > long_press): print("long_press :",long_press) # Stoppe la vidéo print('Stop') omx.action(OmxControl.ACTION_EXIT) # SORTIR DE LA BOUCLE PRINCIPALE sinon la vidéo se relancera elif (elapsed > 0): print("short_press") # Pause/Play la vidéo print('Pause/Play') omx.action(OmxControl.ACTION_PAUSE) GPIO.add_event_detect(PIN_VOLMOINS, GPIO.BOTH, callback=bouton_PIN_VOLMOINS, bouncetime=100) GPIO.add_event_detect(PIN_VOLPLUS, GPIO.BOTH, callback=bouton_PIN_VOLPLUS, bouncetime=100) GPIO.add_event_detect(PIN_PRECEDENT, GPIO.BOTH, callback=bouton_PIN_PRECEDENT, bouncetime=100) GPIO.add_event_detect(PIN_SUIVANT, GPIO.BOTH, callback=bouton_PIN_SUIVANT, bouncetime=100) GPIO.add_event_detect(PIN_PLAY, GPIO.BOTH, callback=bouton_PIN_PLAY, bouncetime=100) ##################### # Boucle Principale # ##################### while True: try: omx = OmxControl() # appel librairie OmxControl except OmxControlError as ex: # si le controle ne voit plus D-Bus, relance la vidéo print("ERREUR de contrôle D-Bus, relance de la vidéo") print('Selection : ',Selection(vid)) subprocess.Popen(['omxplayer','--aspect-mode', 'stretch', '-o', 'local', Selection(vid)], stdin=subprocess.PIPE) time.sleep(3) # tempo pour laisser le temps au player vidéo de démarrer omx = OmxControl() # appel librairie OmxControl omx.action(OmxControl.ACTION_DECREASE_VOLUME) omx.action(OmxControl.ACTION_DECREASE_VOLUME) omx.action(OmxControl.ACTION_DECREASE_VOLUME) omx.action(OmxControl.ACTION_DECREASE_VOLUME) omx.action(OmxControl.ACTION_DECREASE_VOLUME) omx.action(OmxControl.ACTION_DECREASE_VOLUME) # -18 db # on réinitialise les ports GPIO en sortie de script GPIO.cleanup() ##################################################### # Fonctions disponible dans la librairie OmxControl # ##################################################### #ACTION_DECREASE_SPEED #ACTION_INCREASE_SPEED #ACTION_REWIND #ACTION_FAST_FORWARD #ACTION_SHOW_INFO #ACTION_PREVIOUS_AUDIO #ACTION_NEXT_AUDIO #ACTION_PREVIOUS_CHAPTER #ACTION_NEXT_CHAPTER #ACTION_PREVIOUS_SUBTITLE #ACTION_NEXT_SUBTITLE #ACTION_TOGGLE_SUBTITLE #ACTION_DECREASE_SUBTITLE_DELAY #ACTION_INCREASE_SUBTITLE_DELAY #ACTION_EXIT #ACTION_PAUSE #ACTION_DECREASE_VOLUME #ACTION_INCREASE_VOLUME #ACTION_SEEK_BACK_SMALL #ACTION_SEEK_FORWARD_SMALL #ACTION_SEEK_BACK_LARGE #ACTION_SEEK_FORWARD_LARGE #ACTION_SEEK_RELATIVE #ACTION_SEEK_ABSOLUTE #ACTION_STEP #ACTION_BLANK #ACTION_MOVE_VIDEO #ACTION_HIDE_VIDEO #ACTION_UNHIDE_VIDEO #ACTION_HIDE_SUBTITLES
2 - Automatisation :
- Pour démarrer automatiquement le programme python dés le démarrage du Raspberry, on utilise un script bash :
nano /home/pi/arcade.sh
Avec dedans :
#!/bin/bash /usr/local/bin/fbcp & /usr/bin/python3 /home/pi/omxcontrol/VideoOMXcontrol_GPIO_Multifonctions_Playlist.py
- Et puis on ajoute simplement le script dans le .bashrc de l'utilisateur courant[1].
sudo nano /home/pi/.bashrc
À la fin du fichier, renseigner :
echo Lancement du script arcade après le login de l utilisateur pi /bin/bash /home/pi/arcade.sh
C'est terminé pour l'électronique et l'informatique ! Du moins pour le pilotage d'une seule borne.
Plus tard je ferais en sorte de pouvoir piloter chaque borne du Game Center depuis un seul pupitre.
La prochaine fois nous verrons comment intégrer l'écran dans la maquette et nous auront terminé cette Sega Astro City.
À suivre…
Ressources :
https://www.dexterindustries.com/howto/run-a-program-on-your-raspberry-pi-at-startup/
https://stackoverflow.com/questions/36073640/time-between-button-press-and-release-in-python
Note
[1] Pas possible d'utiliser la méthode désormais classique via systemd, car le programme refusait de se lancer à cause d'erreurs avec dbus. Cependant ce n'est pas plus mal, car le programme est lancé par la console loguée sur l'écran LCD, on le voit démarrer à l'allumage du pi.