Nota

Ciao, benvenuto nella Community di appassionati di SunFounder Raspberry Pi & Arduino & ESP32 su Facebook! Approfondisci le tue conoscenze su Raspberry Pi, Arduino ed ESP32 insieme ad altri appassionati.

Perché unirti?

  • Supporto esperto: Risolvi i problemi post-vendita e le sfide tecniche con l’aiuto della nostra community e del nostro team.

  • Impara e Condividi: Scambia consigli e tutorial per migliorare le tue competenze.

  • Anteprime Esclusive: Ottieni accesso anticipato agli annunci di nuovi prodotti e anteprime esclusive.

  • Sconti Speciali: Approfitta di sconti esclusivi sui nostri nuovi prodotti.

  • Promozioni e Omaggi Festivi: Partecipa a omaggi e promozioni speciali per le festività.

👉 Pronto a esplorare e creare con noi? Clicca su [Qui] e unisciti oggi!

4.1.15 GIOCO - 10 Secondi

Introduzione

Seguimi per creare un dispositivo di gioco che metterà alla prova la tua concentrazione. Fissa un interruttore di inclinazione a un bastoncino per creare una bacchetta magica. Agita la bacchetta e il display a 4 cifre inizierà a contare, agitala di nuovo per fermare il conteggio. Se riesci a mantenere il conteggio visualizzato su 10.00, hai vinto. Puoi sfidare i tuoi amici per vedere chi è il mago del tempo.

Componenti Necessari

In questo progetto, abbiamo bisogno dei seguenti componenti.

../_images/4.1.18_game_10_second_list.png

È sicuramente conveniente acquistare un kit completo, ecco il link:

Nome

ELEMENTI IN QUESTO KIT

LINK

Kit Raphael

337

Raphael Kit

Puoi anche acquistare i componenti separatamente dai link sottostanti.

INTRODUZIONE AI COMPONENTI

LINK PER L’ACQUISTO

Scheda di estensione GPIO

ACQUISTA

Breadboard

ACQUISTA

Cavi Jumper

ACQUISTA

Resistore

ACQUISTA

Display a 7 Segmenti da 4 Cifre

-

74HC595

ACQUISTA

Interruttore di Inclinazione

-

Schema del Circuito

T-Board Name

physical

wiringPi

BCM

GPIO17

Pin 11

0

17

GPIO27

Pin 13

2

27

GPIO22

Pin 15

3

22

SPIMOSI

Pin 19

12

10

GPIO18

Pin 12

1

18

GPIO23

Pin 16

4

23

GPIO24

Pin 18

5

24

GPIO26

Pin 37

25

26

../_images/4.1.18_game_10_second_schematic.png

Procedure Sperimentali

Passo 1: Assembla il circuito.

../_images/4.1.18_game_10_second_circuit.png

Passo 2: Vai alla cartella del codice.

cd ~/raphael-kit/python-pi5

Passo 3: Esegui il file eseguibile.

sudo python3 4.1.18_GAME_10Second_zero.py

Agita la bacchetta, il display a 4 cifre inizierà a contare, agitala di nuovo per fermare il conteggio. Se riesci a mantenere il conteggio visualizzato su 10.00, hai vinto. Agita ancora una volta per iniziare il prossimo round del gioco.

Avvertimento

Se viene visualizzato l’errore RuntimeError: Cannot determine SOC peripheral base address, fare riferimento a If gpiozero doesn’t work..

Code

Nota

Puoi Modificare/Reimpostare/Copiare/Eseguire/Interrompere il codice qui sotto. Tuttavia, prima di farlo, devi accedere al percorso sorgente del codice, come ad esempio raphael-kit/python-pi5. Dopo aver modificato il codice, puoi eseguirlo direttamente per vedere l’effetto.

#!/usr/bin/env python3

from gpiozero import OutputDevice, Button
import time
import threading

# Inizializza il pulsante collegato al GPIO 26
sensorPin = Button(26)

# Definisce i pin GPIO collegati al registro a scorrimento 74HC595
SDI = OutputDevice(24)   # Input dati seriali
RCLK = OutputDevice(23)  # Clock del registro
SRCLK = OutputDevice(18) # Clock del registro a scorrimento

# Definisce i pin GPIO per la selezione delle cifre sul display a 7 segmenti
placePin = [OutputDevice(pin) for pin in (10, 22, 27, 17)]

# Definisce i codici per i segmenti dei numeri da 0 a 9 sul display a 7 segmenti
number = (0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90)

# Variabili per il contatore e il timer
counter = 0
timer1 = None
gameState = 0

def clearDisplay():
    """ Clear all segments on the 7-segment display. """
    for _ in range(8):
        SDI.on()
        SRCLK.on()
        SRCLK.off()
    RCLK.on()
    RCLK.off()

def hc595_shift(data):
    """ Shift data to the 74HC595 shift register to display a digit. """
    for i in range(8):
        SDI.value = 0x80 & (data << i)
        SRCLK.on()
        SRCLK.off()
    RCLK.on()
    RCLK.off()

def pickDigit(digit):
    """ Select which digit to display on the 7-segment display. """
    for pin in placePin:
        pin.off()
    placePin[digit].on()

def display():
    """ Display the current counter value on the 7-segment display. """
    global counter
    clearDisplay()
    pickDigit(0)
    hc595_shift(number[counter % 10])

    clearDisplay()
    pickDigit(1)
    hc595_shift(number[counter % 100 // 10])

    clearDisplay()
    pickDigit(2)
    hc595_shift(number[counter % 1000 // 100] - 0x80)

    clearDisplay()
    pickDigit(3)
    hc595_shift(number[counter % 10000 // 1000])

def stateChange():
    """ Handle state changes for the counter based on button presses. """
    global gameState, counter, timer1
    if gameState == 0:
        counter = 0
        time.sleep(1)
        timer()
    elif gameState == 1 and timer1 is not None:
        timer1.cancel()
        time.sleep(1)
    gameState = (gameState + 1) % 2

def loop():
    """ Main loop to check for button presses and update the display. """
    global counter
    currentState = 0
    lastState = 0
    while True:
        display()
        currentState = sensorPin.value
        if (currentState == 0) and (lastState == 1):
            stateChange()
        lastState = currentState

def timer():
    """ Timer function that increments the counter every 0.01 second. """
    global counter, timer1
    timer1 = threading.Timer(0.01, timer)
    timer1.start()
    counter += 1

try:
    loop()
except KeyboardInterrupt:
    if timer1:
        timer1.cancel()

Spiegazione del Codice

  1. Lo script inizia importando i moduli necessari. La libreria gpiozero viene utilizzata per interfacciarsi con i dispositivi GPIO come i pulsanti, mentre i moduli time e threading possono essere utilizzati per gestire operazioni relative al tempo o simultanee.

    #!/usr/bin/env python3
    
    from gpiozero import OutputDevice, Button
    import time
    import threading
    
  2. Inizializza un oggetto Button dalla libreria GPIO Zero, collegandolo al pin GPIO 26. Questa configurazione consente il rilevamento delle pressioni del pulsante.

    # Inizializza il pulsante collegato al GPIO 26
    sensorPin = Button(26)
    
  3. Inizializza i pin GPIO collegati agli ingressi Serial Data Input (SDI), Register Clock Input (RCLK) e Shift Register Clock Input (SRCLK) del registro a scorrimento.

    # Definisce i pin GPIO collegati al registro a scorrimento 74HC595
    SDI = OutputDevice(24)   # Input dati seriali
    RCLK = OutputDevice(23)  # Clock del registro
    SRCLK = OutputDevice(18) # Clock del registro a scorrimento
    
  4. Inizializza i pin per ciascuna cifra del display a 7 segmenti e definisce i codici binari per visualizzare i numeri da 0 a 9.

    # Definisce i pin GPIO per la selezione delle cifre sul display a 7 segmenti
    placePin = [OutputDevice(pin) for pin in (10, 22, 27, 17)]
    
    # Definisce i codici per i segmenti dei numeri da 0 a 9 sul display a 7 segmenti
    number = (0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90)
    
  5. Funzioni per controllare il display a 7 segmenti. clearDisplay spegne tutti i segmenti, hc595_shift sposta i dati nel registro a scorrimento, e pickDigit attiva una cifra specifica sul display.

    def clearDisplay():
        """ Clear all segments on the 7-segment display. """
        for _ in range(8):
            SDI.on()
            SRCLK.on()
            SRCLK.off()
        RCLK.on()
        RCLK.off()
    
    def hc595_shift(data):
        """ Shift data to the 74HC595 shift register to display a digit. """
        for i in range(8):
            SDI.value = 0x80 & (data << i)
            SRCLK.on()
            SRCLK.off()
        RCLK.on()
        RCLK.off()
    
    def pickDigit(digit):
        """ Select which digit to display on the 7-segment display. """
        for pin in placePin:
            pin.off()
        placePin[digit].on()
    
  6. Funzione per visualizzare il valore corrente del contatore sul display a 7 segmenti.

    def display():
        """ Display the current counter value on the 7-segment display. """
        global counter
        clearDisplay()
        pickDigit(0)
        hc595_shift(number[counter % 10])
    
        clearDisplay()
        pickDigit(1)
        hc595_shift(number[counter % 100 // 10])
    
        clearDisplay()
        pickDigit(2)
        hc595_shift(number[counter % 1000 // 100] - 0x80)
    
        clearDisplay()
        pickDigit(3)
        hc595_shift(number[counter % 10000 // 1000])
    
  7. Funzione per gestire i cambi di stato (avvio/arresto) del contatore in base alle pressioni del pulsante.

    def stateChange():
        """ Handle state changes for the counter based on button presses. """
        global gameState, counter, timer1
        if gameState == 0:
            counter = 0
            time.sleep(1)
            timer()
        elif gameState == 1 and timer1 is not None:
            timer1.cancel()
            time.sleep(1)
        gameState = (gameState + 1) % 2
    
  8. Ciclo principale che controlla continuamente lo stato del pulsante e aggiorna il display. Richiama stateChange quando lo stato del pulsante cambia.

    def loop():
        """ Main loop to check for button presses and update the display. """
        global counter
        currentState = 0
        lastState = 0
        while True:
            display()
            currentState = sensorPin.value
            if (currentState == 0) and (lastState == 1):
                stateChange()
            lastState = currentState
    
  9. Funzione timer che incrementa il contatore a intervalli regolari (ogni 0,01 secondi).

    def timer():
        """ Timer function that increments the counter every 0.01 second. """
        global counter, timer1
        timer1 = threading.Timer(0.01, timer)
        timer1.start()
        counter += 1
    
  10. Esegue il ciclo principale e consente un’uscita pulita dal programma utilizzando un’interruzione della tastiera (Ctrl+C).

    try:
        loop()
    except KeyboardInterrupt:
        if timer1:
            timer1.cancel()