.. note:: Ciao, benvenuto nella Community di Appassionati di SunFounder Raspberry Pi, Arduino & ESP32 su Facebook! Approfondisci Raspberry Pi, Arduino ed ESP32 con altri appassionati. **Perché unirsi?** - **Supporto Esperto**: Risolvi problemi post-vendita e sfide tecniche con l’aiuto della nostra community e del nostro team. - **Impara & Condividi**: Scambia suggerimenti e tutorial per migliorare le tue abilità. - **Anteprime Esclusive**: Ottieni l'accesso anticipato agli annunci di nuovi prodotti e anteprime. - **Sconti Speciali**: Approfitta di sconti esclusivi sui nostri prodotti più recenti. - **Promozioni Festive e Giveaway**: Partecipa a giveaway e promozioni festive. 👉 Pronto a esplorare e creare con noi? Clicca [|link_sf_facebook|] e unisciti oggi stesso! 3.1.14 GIOCO– Not Not ======================= Introduzione -------------------- In questa lezione, realizzeremo un dispositivo per un gioco interessante, che chiamiamo "Not Not". Durante il gioco, la matrice di punti genererà casualmente una freccia. Il tuo compito sarà premere il pulsante nella direzione opposta alla freccia entro un tempo limitato. Se il tempo scade, o se premi il pulsante nella stessa direzione della freccia, perdi. Questo gioco può davvero allenare il tuo pensiero inverso, quindi, pronto a fare una prova? Componenti --------------- .. image:: img/list_GAME_Not_Not.png :align: center Schema a Blocchi ----------------------- ============ ======== ======== === 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 Procedura Sperimentale ----------------------------- **Passo 1:** Assembla il circuito. .. image:: img/image280.png :width: 800 **Per Utenti C Language** ^^^^^^^^^^^^^^^^^^^^^^^^^^ **Passo 2:** Vai alla cartella del codice. .. raw:: html .. code-block:: cd ~/davinci-kit-for-raspberry-pi/c/3.1.14/ **Passo 3**: Compila il codice. .. raw:: html .. code-block:: gcc 3.1.14_GAME_NotNot.c -lwiringPi **Passo 4**: Esegui il file eseguibile. .. raw:: html .. code-block:: sudo ./a.out Dopo l’avvio del programma, sul display a matrice di punti apparirà casualmente una freccia verso destra o sinistra. Devi premere il pulsante nella direzione opposta alla freccia entro un tempo limitato. Successivamente apparirà \"**√**\" sulla matrice di punti. Se il tempo scade o premi il pulsante nella stessa direzione della freccia, perdi e la matrice di punti visualizzerà una \"x\". Puoi anche aggiungere 2 nuovi pulsanti o sostituirli con i tasti del joystick per le direzioni su, giù, sinistra e destra, aumentando così la difficoltà del gioco. .. note:: Se il programma non funziona dopo l’avvio o compare un messaggio di errore: \"wiringPi.h: No such file or directory\", fai riferimento a :ref:`Il codice C non funziona?`. **Spiegazione del Codice** Basato su **1.1.6 Matrice di LED**, questa lezione aggiunge **2** pulsanti per creare un dispositivo di gioco divertente. Se non hai familiarità con la matrice di punti, fai riferimento a :ref:`1.1.6 Matrice di LED`. Il processo dell'intero programma è il seguente: 1. Seleziona casualmente una direzione per la freccia e genera **timer 1**. 2. Mostra l'immagine della freccia sulla matrice di punti. 3. Verifica l'input del pulsante. Se il pulsante viene premuto o **timer 1** segnala la scadenza del tempo, inizia il giudizio. 4. Visualizza l'immagine in base al risultato del giudizio; contemporaneamente, genera **timer 2**. 5. Ripeti il **passo 1** quando **timer 2** segnala la scadenza del tempo. .. 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 struttura GLYPH funziona come un dizionario: l’attributo **word** corrisponde alla **chiave** del dizionario, mentre **code** corrisponde al **valore**. Il **code** serve a memorizzare un array per visualizzare immagini sulla matrice (un array di 8x8 bit). L’array **arrow** può visualizzare le frecce nelle direzioni sinistra e destra sulla matrice LED. Ora **down** e **up** sono commentati: puoi attivarli se necessario. L’array **check** serve a visualizzare due immagini: \"**×**\" e \"**√**\". .. code-block:: c char *lookup(char *key,struct GLYPH *glyph,int length){     for (int i=0;i>i); hc595_out(); } } Visualizza il pattern specificato sulla matrice di punti. .. 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 funzione **createGlyph()** seleziona casualmente una direzione (l'attributo word di un elemento nell'array **arrow[]:** \"**left**\", \"**right**\"...). Imposta lo **stage** su "PLAY" e avvia una sveglia di 2 secondi. **srand(time(NULL)):** Inizializza semi casuali dall'orologio di sistema. **(sizeof(arrow)/sizeof(arrow[0])):** Ottieni la lunghezza dell’array, il risultato è 2. **rand()%2:** Ritorna **0** o **1** dividendo il numero casuale generato per 2. **waypoint=arrow[i].word:** Il risultato è \"right\" o \"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() verifica l'input del pulsante; se non viene premuto o se si preme il pulsante nella stessa direzione della freccia, il risultato del waypoint è errato e compare \"x\" sulla matrice. Altrimenti, il waypoint è corretto e la matrice visualizza \"√\". Qui lo **stage** è **CHECK**, e si può impostare una sveglia di 1 secondo. alarm() è una sveglia, in cui si può impostare un timer che invia segnali **SIGALRM** al processo al termine del tempo definito. .. 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() legge gli stati dei due pulsanti; se viene premuto quello destro, il parametro di checkPoint() è **right**, se si preme quello sinistro, il parametro è **left**. .. code-block:: c void timer(){     if (stage=="PLAY"){ checkPoint("empty"); }     else if(stage=="CHECK"){ createGlyph(); } } Precedentemente, timer() veniva richiamato allo scadere di alarm(). Sotto la modalità \"PLAY\", checkPoint() viene chiamato per giudicare l’esito. Se è in modalità \"CHECK\", si richiama createGlyph() per selezionare nuovi pattern. .. 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); } } } Il funzionamento di signal(SIGALRM,timer): chiama la funzione timer() alla ricezione di un segnale SIGALRM generato dalla funzione sveglia alarm(). All’avvio, crea una freccia con createGlyph() e inizia il loop. Nel ciclo: in modalità PLAY, la matrice visualizza la freccia e verifica lo stato del pulsante; in modalità CHECK, visualizza \"x\" o \"√\". **Per Utenti Python** ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Step 2**: Entra nella cartella del codice. .. raw:: html .. code-block:: cd ~/davinci-kit-for-raspberry-pi/python **Step 3**: Esegui. .. raw:: html .. code-block:: sudo python3 3.1.14_GAME_NotNot.py Dopo l’avvio del programma, sulla matrice compare una freccia verso destra o sinistra. Devi premere il pulsante nella direzione opposta entro un tempo limitato. A quel punto, \"√\" appare sulla matrice. Se il tempo scade o se il pulsante è nella stessa direzione della freccia, perdi e la matrice mostra \"x\". Puoi anche aggiungere 2 pulsanti o sostituirli con i tasti del Joystick per le direzioni su, giù, sinistra e destra, aumentando la difficoltà del gioco. **Codice** .. note:: Puoi **Modificare/Reset/Copiare/Eseguire/Interrompere** il codice qui sotto. Prima di farlo, devi andare nel percorso sorgente del codice, come ``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) # Numero GPIOs in base alla loro posizione 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) # Trasferisce i dati al 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() # cancella il timer timerCheck.cancel() if __name__ == '__main__': setup() try: main() except KeyboardInterrupt: destroy() **Spiegazione del Codice** Basato su **1.1.6 Matrice a LED**, questa lezione aggiunge **2** pulsanti per creare un dispositivo di gioco divertente. Se non hai molta familiarità con la matrice di punti, fai riferimento a :ref:`1.1.6 Matrice di LED`. Il processo completo del programma è il seguente: .. image:: img/notnot3.png :width: 800 1. Seleziona casualmente una direzione della freccia e genera **timer 1**. 2. Visualizza l'immagine della freccia corrispondente sulla matrice a punti. 3. Rileva l'input del pulsante. Se viene premuto il pulsante o **timer 1** segnala lo scadere del tempo, inizia il giudizio. 4. Visualizza l'immagine in base al risultato del giudizio; contemporaneamente, genera **timer 2**. 5. Ripeti **passo 1** quando **timer 2** segnala lo scadere del tempo. .. code-block:: python def main(): creatGlyph()     while True:         if stage == "PLAY": display(arrow[waypoint]) getKey()         elif stage == "CHECK": display(check[waypoint]) Main() contiene l'intero processo di esecuzione. Quando il programma inizia, chiama creatGlyph() una volta e poi avvia il ciclo. Nel ciclo: in modalità PLAY, la matrice a punti mostra i modelli di freccia e verifica lo stato del pulsante; se in modalità CHECK, viene visualizzato "**x**" o "**√**". .. 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] } Qui, il **dizionario** arrow può essere utilizzato per mostrare il modello di freccia in su, giù, sinistra e destra sulla matrice LED. Attualmente, giù e su sono commentati e puoi rimuovere i commenti se necessario. Il **dizionario** check è utilizzato per visualizzare queste due immagini: "**×**" e "**√**". .. 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) Mostra il modello specificato sulla matrice a punti. .. 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 funzione **createGlyph()** viene utilizzata per selezionare casualmente una direzione (l'attributo word di un elemento nell'array **arrow[]:** "left", "right" ... ). Imposta lo stage su "PLAY" e avvia una funzione timer di 2 secondi. **arrow.keys():** Seleziona le chiavi "right" e "left" nell'array arrow. **list(arrow.keys()):** Combina queste chiavi in un array. **random.choice(list(arrow.keys())):** Seleziona casualmente un elemento nell'array. Quindi, il risultato di **waypoint=random.choice(list(arrow.keys()))** sarà "right" o "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() serve per rilevare lo stato attuale dell'input del pulsante: Se non viene premuto nessun pulsante o viene premuto il pulsante nella stessa direzione della freccia, il valore assegnato a **``waypoint``** è **``wrong``** e appare "x" sulla matrice a punti. Altrimenti, waypoint è "right" e appare "**√**". Ora lo stage è **CHECK** e avvia un timer di 1 secondo **timerCheck** per chiamare la funzione creatGlyph() dopo un secondo. .. code-block:: python def timeOut():   checkPoint("empty") Nella funzione timeout(), imposta il parametro di checkPoint() come "**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() legge lo stato di questi due pulsanti e, se viene premuto il pulsante destro, il parametro di checkPoint() è **right**; se viene premuto il pulsante sinistro, il parametro è **left**. Immagine del Fenomeno ------------------------- .. image:: img/image281.jpeg :align: center