.. note:: Bonjour, bienvenue dans la communauté des passionnés de SunFounder Raspberry Pi & Arduino & ESP32 sur Facebook ! Plongez plus profondément dans l'univers de Raspberry Pi, Arduino et ESP32 avec d'autres passionnés. **Pourquoi nous rejoindre ?** - **Support d'experts** : Résolvez les problèmes après-vente et les défis techniques grâce à l'aide de notre communauté et de notre équipe. - **Apprendre et partager** : Échangez des astuces et des tutoriels pour améliorer vos compétences. - **Aperçus exclusifs** : Obtenez un accès anticipé aux annonces de nouveaux produits et aux avant-premières. - **Réductions spéciales** : Profitez de remises exclusives sur nos derniers produits. - **Promotions festives et cadeaux** : Participez à des tirages au sort et à des promotions spéciales pendant les fêtes. 👉 Prêt à explorer et à créer avec nous ? Cliquez sur [|link_sf_facebook|] et rejoignez-nous dès aujourd'hui ! 3.1.14 JEU - Not Not ======================= Introduction -------------------- Dans cette leçon, nous allons fabriquer un dispositif de jeu intéressant que nous appelons "Not Not". Pendant le jeu, la matrice à points rafraîchira une flèche aléatoire. Votre tâche est d'appuyer sur le bouton dans la direction opposée à la flèche dans un délai imparti. Si le temps est écoulé ou si vous appuyez sur le bouton dans la même direction que la flèche, vous perdez. Ce jeu vous permet de pratiquer votre pensée inversée. Alors, êtes-vous prêt à essayer ? Composants --------------- .. image:: img/list_GAME_Not_Not.png :align: center Schéma de câblage ----------------------- ============ ======== ======== === T-Board Name physical wiringPi BCM GPIO17 Pin 11 0 17 GPIO18 Pin 12 1 18 GPIO27 Pin 13 2 27 GPIO20 Pin 38 28 20 GPIO26 Pin 37 25 26 ============ ======== ======== === .. image:: img/Schematic_three_one14.png :align: center Procédures expérimentales ----------------------------- **Étape 1 :** Construisez le circuit. .. image:: img/image280.png :width: 800 **Pour les utilisateurs du langage C** ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Étape 2 :** Allez dans le dossier du code. .. raw:: html .. code-block:: cd ~/davinci-kit-for-raspberry-pi/c/3.1.14/ **Étape 3 :** Compilez. .. raw:: html .. code-block:: gcc 3.1.14_GAME_NotNot.c -lwiringPi **Étape 4 :** Exécutez le fichier. .. raw:: html .. code-block:: sudo ./a.out Après le démarrage du programme, une flèche gauche ou droite s'affiche aléatoirement sur la matrice de points. Vous devez appuyer sur le bouton dans la direction opposée à la flèche dans un temps imparti. Ensuite, un \"**√**\" apparaîtra sur la matrice de points. Si le temps est écoulé ou si vous appuyez sur le bouton dans la même direction que la flèche, vous perdez et la matrice affiche \"x\". Vous pouvez également ajouter 2 nouveaux boutons ou les remplacer par des touches de joystick pour avoir 4 directions (haut, bas, gauche, droite) et augmenter la difficulté du jeu. .. note:: Si le programme ne fonctionne pas après l'exécution ou si un message d'erreur apparaît : \"wiringPi.h: Aucun fichier ou répertoire de ce type", veuillez consulter :ref:`C code is not working?`. **Explication du code** Basé sur **1.1.6 Matrice LED**, cette leçon ajoute **2** boutons pour créer un dispositif de jeu amusant. Donc, si vous n'êtes pas très familier avec la matrice à points, veuillez consulter:ref:`1.1.6 LED Dot Matrix`. Le processus du programme complet est le suivant : 1. Sélectionnez aléatoirement une direction de flèche et générez **timer 1**. 2. Affichez l'image de la flèche sur la matrice de points. 3. Vérifiez l'entrée du bouton. Si le bouton est pressé ou si **timer 1** signale la fin du délai, commencez la vérification. 4. Affichez l'image selon le résultat de la vérification ; en parallèle, générez **timer 2**. 5. Reprenez **étape 1** lorsque **timer 2** indique la fin du délai. .. code-block:: c struct GLYPH{     char *word;     unsigned char code[8]; }; struct GLYPH arrow[2]= { {"right",{0xFF,0xEF,0xDF,0x81,0xDF,0xEF,0xFF,0xFF}}, // {"down",{0xFF,0xEF,0xC7,0xAB,0xEF,0xEF,0xEF,0xFF}}, // {"up",{0xFF,0xEF,0xEF,0xEF,0xAB,0xC7,0xEF,0xFF}}, {"left",{0xFF,0xF7,0xFB,0x81,0xFB,0xF7,0xFF,0xFF}} }; struct GLYPH check[2]= { {"wrong",{0xFF,0xBB,0xD7,0xEF,0xD7,0xBB,0xFF,0xFF}}, {"right",{0xFF,0xFF,0xF7,0xEB,0xDF,0xBF,0xFF,0xFF}} }; La structure GLYPH fonctionne comme un dictionnaire : l'attribut **word** correspond à la **clé** du dictionnaire ; l'attribut **code** correspond à la **valeur**. Ici, le code est utilisé pour stocker un tableau permettant d'afficher des images sur la matrice à points (un tableau de 8x8 bits). Le tableau **arrow** peut être utilisé pour afficher les motifs de flèches dans les directions haut, bas, gauche et droite sur la matrice LED. Maintenant, **down** et **up** sont commentés, vous pouvez les décommenter si nécessaire. Le tableau **check** est utilisé pour afficher ces deux images : \"**×**\" et \"**√**\". .. code-block:: c char *lookup(char *key,struct GLYPH *glyph,int length){     for (int i=0;i>i); hc595_out(); } } Affiche le motif spécifié sur la matrice à points. .. code-block:: c void createGlyph(){ srand(time(NULL));     int i=rand()%(sizeof(arrow)/sizeof(arrow[0])); waypoint=arrow[i].word; stage="PLAY"; alarm(2); } La fonction **createGlyph()** sélectionne aléatoirement une direction (l'attribut word d'un élément du tableau **arrow[]:** \"**left**\", \"**right**\"... ). Définit le stage sur \"PLAY\" et démarre une alarme de 2 secondes. **srand(time(NULL)) :** Initialise des graines aléatoires à partir de l'horloge du système. **(sizeof(arrow)/sizeof(arrow[0])):** Calcule la longueur du tableau, qui est 2. **rand()%2 :** Le reste est **0** ou **1,** obtenu en divisant un nombre aléatoire généré par 2. **waypoint=arrow[i].word :** Le résultat doit être \"right\" ou \"left\". .. code-block:: c void checkPoint(char *inputKey){ alarm(0)==0; if(inputKey==waypoint||inputKey=="empty") { waypoint="wrong"; } else{ waypoint="right"; } stage="CHECK"; alarm(1); } **checkPoint()** vérifie l'entrée du bouton ; si le bouton n'est pas pressé ou si le bouton appuyé est dans la même direction que la flèche, le résultat de **waypoint** est \"wrong\" et un \"**x**\" apparaît sur la matrice de points. Sinon, **waypoint** est \"right\" et la matrice affiche \"**√**\". Ici, le **stage** est **CHECK**, et une alarme de 1 seconde peut être définie. **alarm()** est aussi appelé "réveil", dans lequel un minuteur peut être défini, envoyant des signaux **SIGALRM** lorsque le temps défini est écoulé. .. code-block:: c void getKey(){     if (digitalRead(AButtonPin)==1&&digitalRead(BButtonPin)==0) {checkPoint("right");}     else if (digitalRead(AButtonPin)==0&&digitalRead(BButtonPin)==1) {checkPoint("left");} } **getKey()** lit les états de ces deux boutons ; si le bouton droit est pressé, le paramètre de **checkPoint()** est **right** et si le bouton gauche est pressé, le paramètre est **left**. .. code-block:: c void timer(){     if (stage=="PLAY"){ checkPoint("empty"); }     else if(stage=="CHECK"){ createGlyph(); } } Précédemment, **timer()** était appelé lorsque **alarm()** déclenchait la fin du temps imparti. En mode \"PLAY\", **checkPoint()** est appelé pour juger le résultat. Si le programme est en mode \"CHECK\", la fonction **createGlyph()** doit être appelée pour sélectionner de nouveaux motifs. .. code-block:: c void main(){ setup(); signal(SIGALRM,timer); createGlyph();     char *code = NULL; while(1){         if (stage == "PLAY") { code=lookup(waypoint,arrow,sizeof(arrow)/sizeof(arrow[0])); display(code); getKey(); }         else if(stage == "CHECK") {             code = lookup(waypoint,check,sizeof(check)/sizeof(check[0])); display(code); } } } Le fonctionnement de **signal(SIGALRM,timer) :** appel de la fonction **timer()** lorsqu'un signal **SIGALRM** (généré par la fonction réveil **alarm()**) est reçu. Lorsque le programme commence, appelez d'abord **createGlyph()**, puis démarrez la boucle. Dans la boucle : en mode PLAY, la matrice de points affiche les motifs de flèches et vérifie l'état des boutons ; si en mode CHECK, ce qui est affiché est \"**x**\" ou \"**√**\". **Pour les utilisateurs du langage Python** ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Étape 2** : Accédez au dossier contenant le code. .. raw:: html .. code-block:: cd ~/davinci-kit-for-raspberry-pi/python **Étape 3** : Exécutez le code. .. raw:: html .. code-block:: sudo python3 3.1.14_GAME_NotNot.py Après avoir lancé le programme, une flèche pointant vers la droite ou la gauche apparaîtra sur la matrice de points. Votre tâche consiste à appuyer sur le bouton dans la direction opposée à la flèche dans un délai imparti. Ensuite, un \"**√**\" s'affichera sur la matrice de points. Si le temps est écoulé ou si vous appuyez sur le bouton dans la même direction que la flèche, vous perdez et la matrice affichera un \"x\". Vous pouvez également ajouter 2 nouveaux boutons ou les remplacer par des touches de joystick pour avoir 4 directions (haut, bas, gauche et droite) et augmenter la difficulté du jeu. **Code** .. note:: Vous pouvez **Modifier/Réinitialiser/Copier/Exécuter/Arrêter** le code ci-dessous. Mais avant cela, vous devez accéder au chemin source du code comme ``davinci-kit-for-raspberry-pi/python``. .. raw:: html .. code-block:: python import RPi.GPIO as GPIO import time import threading import random SDI = 17 RCLK = 18 SRCLK = 27 timerPlay = 0 timerCheck = 0 AButtonPin = 20 BButtonPin = 26 waypoint = "NULL" stage = "NULL" arrow={ #"down" :[0xFF,0xEF,0xC7,0xAB,0xEF,0xEF,0xEF,0xFF], #"up":[0xFF,0xEF,0xEF,0xEF,0xAB,0xC7,0xEF,0xFF], "right" : [0xFF,0xEF,0xDF,0x81,0xDF,0xEF,0xFF,0xFF], "left":[0xFF,0xF7,0xFB,0x81,0xFB,0xF7,0xFF,0xFF] } check={ "wrong":[0xFF,0xBB,0xD7,0xEF,0xD7,0xBB,0xFF,0xFF], "right":[0xFF,0xFF,0xF7,0xEB,0xDF,0xBF,0xFF,0xFF] } def setup(): GPIO.setmode(GPIO.BCM) # Numérotation des GPIOs par leur emplacement BCM GPIO.setup(SDI, GPIO.OUT) GPIO.setup(RCLK, GPIO.OUT) GPIO.setup(SRCLK, GPIO.OUT) GPIO.output(SDI, GPIO.LOW) GPIO.output(RCLK, GPIO.LOW) GPIO.output(SRCLK, GPIO.LOW) GPIO.setup(AButtonPin,GPIO.IN) GPIO.setup(BButtonPin,GPIO.IN) # Transférer les données vers le 74HC595 def hc595_shift(dat): for bit in range(0, 8): GPIO.output(SDI, 0x80 & (dat << bit)) GPIO.output(SRCLK, GPIO.HIGH) GPIO.output(SRCLK, GPIO.LOW) def display(glyphCode): for i in range(0, 8): hc595_shift(glyphCode[i]) hc595_shift(0x80>>i) GPIO.output(RCLK, GPIO.HIGH) GPIO.output(RCLK, GPIO.LOW) def creatGlyph(): global waypoint global stage global timerPlay waypoint=random.choice(list(arrow.keys())) stage = "PLAY" timerPlay = threading.Timer(2.0, timeOut) timerPlay.start() def checkPoint(inputKey): global waypoint global stage global timerCheck if inputKey == "empty" or inputKey == waypoint: waypoint = "wrong" else: waypoint = "right" timerPlay.cancel() stage = "CHECK" timerCheck = threading.Timer(1.0, creatGlyph) timerCheck.start() def timeOut(): checkPoint("empty") def getKey(): if GPIO.input(AButtonPin)==1 and GPIO.input(BButtonPin)==0: checkPoint("right") elif GPIO.input(AButtonPin)==0 and GPIO.input(BButtonPin)==1: checkPoint("left") def main(): creatGlyph() while True: if stage == "PLAY": display(arrow[waypoint]) getKey() elif stage == "CHECK": display(check[waypoint]) def destroy(): global timer1 GPIO.cleanup() timerPlay.cancel() # annuler le minuteur timerCheck.cancel() if __name__ == '__main__': setup() try: main() except KeyboardInterrupt: destroy() **Explication du Code** Basé sur **1.1.6 Matrice de LED**, cette leçon ajoute **2** boutons pour créer un dispositif de jeu amusant. Donc, si vous n'êtes pas très familier avec la matrice de points, veuillez vous référer à :ref:`1.1.6 LED Dot Matrix`. Le déroulement complet du programme est le suivant : .. image:: img/notnot3.png :width: 800 1. Sélectionner aléatoirement une direction de flèche et générer le **timer 1**. 2. Afficher l'image de la flèche correspondante sur la matrice de points. 3. Évaluer l'entrée du bouton. Si un bouton est pressé ou si le **timer 1** indique la fin du temps, le jugement commence. 4. Afficher l'image basée sur le résultat du jugement ; simultanément, générer le **timer 2**. 5. Reprendre à l'**étape 1** lorsque le **timer 2** signale la fin du temps. .. code-block:: python def main(): creatGlyph()     while True:         if stage == "PLAY": display(arrow[waypoint]) getKey()         elif stage == "CHECK": display(check[waypoint]) Main() contient l'ensemble du processus de fonctionnement. Lorsque le programme démarre, creatGlyph() est appelé une fois au début, puis la boucle démarre. Dans la boucle : en mode PLAY, la matrice de points affiche des motifs de flèches et vérifie l'état des boutons ; en mode CHECK, ce qui est affiché est soit \"**x**\" soit \"**√**\". .. code-block:: python arrow={ #"down" :[0xFF,0xEF,0xC7,0xAB,0xEF,0xEF,0xEF,0xFF], #"up":[0xFF,0xEF,0xEF,0xEF,0xAB,0xC7,0xEF,0xFF],     "right" : [0xFF,0xEF,0xDF,0x81,0xDF,0xEF,0xFF,0xFF],     "left":[0xFF,0xF7,0xFB,0x81,0xFB,0xF7,0xFF,0xFF] } check={ "wrong":[0xFF,0xBB,0xD7,0xEF,0xD7,0xBB,0xFF,0xFF], "right":[0xFF,0xFF,0xF7,0xEB,0xDF,0xBF,0xFF,0xFF] } Ici, le **dictionnaire** arrow permet d'afficher les motifs de flèches dans les directions haut, bas, gauche et droite sur la matrice de LED. Actuellement, les flèches haut et bas sont commentées, et vous pouvez les décommenter si nécessaire. Le **dictionnaire** check est utilisé pour afficher les deux images : \"**×**\" et \"**√**\". .. code-block:: python def display(glyphCode):     for i in range(0, 8): hc595_shift(glyphCode[i]) hc595_shift(0x80>>i)         GPIO.output(RCLK, GPIO.HIGH)         GPIO.output(RCLK, GPIO.LOW) Afficher le motif spécifié sur la matrice de points. .. code-block:: python def creatGlyph():     global waypoint     global stage     global timerPlay     waypoint=random.choice(list(arrow.keys()))     stage = "PLAY"     timerPlay = threading.Timer(2.0, timeOut)   timerPlay.start() La fonction **createGlyph()** est utilisée pour sélectionner aléatoirement une direction (l'attribut mot d'un élément dans le tableau **arrow[] :** \"**left**\", \"**right**\"... ). Définir l'étape en \"PLAY\" et démarrer une fonction d'alarme de 2 secondes. **arrow.keys():** Sélectionne les clés \"right\" et \"left\" dans le tableau arrow. **list(arrow.keys()):** Combine ces clés en un tableau. **random.choice(list(arrow.keys())):** Sélectionne aléatoirement un élément du tableau. Ainsi, le résultat de **waypoint=random.choice(list(arrow.keys()))** devrait être \"right\" ou \"left\". .. code-block:: python def checkPoint(inputKey):     global waypoint     global stage     global timerCheck         if inputKey == "empty" or inputKey == waypoint:         waypoint = "wrong" else:         waypoint = "right" timerPlay.cancel()     stage = "CHECK"     timerCheck = threading.Timer(1.0, creatGlyph) timerCheck.start() checkPoint() est utilisé pour détecter l'état actuel de l'entrée du bouton : Si aucun bouton n'est pressé ou si le bouton dans la même direction que la flèche est pressé, la valeur assignée au **``waypoint``** est **``wrong``** et un ``x`` s'affiche sur la matrice de points. Sinon, le waypoint est correct et \"**√**\" apparaît. Maintenant, l'étape est **CHECK** et un minuteur de 1 seconde **timerCheck** est démarré pour appeler la fonction creatGlyph() dans une seconde. .. code-block:: python def timeOut():   checkPoint("empty") Dans la fonction timeout(), le paramètre de checkPoint() est défini sur \"**empty**\". .. code-block:: python def getKey():     if GPIO.input(AButtonPin)==1 and GPIO.input(BButtonPin)==0: checkPoint("right")     elif GPIO.input(AButtonPin)==0 and GPIO.input(BButtonPin)==1: checkPoint("left") getKey() lit l'état de ces deux boutons, et si le bouton droit est pressé, le paramètre de checkPoint() est **right** ; si le bouton gauche est pressé, le paramètre est **left**. Image de Démonstration ------------------------------ .. image:: img/image281.jpeg :align: center