Nota

¡Hola! Bienvenido a la Comunidad de Entusiastas de SunFounder Raspberry Pi & Arduino & ESP32 en Facebook. Profundiza en Raspberry Pi, Arduino y ESP32 con otros entusiastas.

¿Por qué unirse?

  • Soporte experto: Resuelve problemas postventa y desafíos técnicos con la ayuda de nuestra comunidad y equipo.

  • Aprende y comparte: Intercambia consejos y tutoriales para mejorar tus habilidades.

  • Avances exclusivos: Obtén acceso anticipado a anuncios de nuevos productos y vistas previas.

  • Descuentos especiales: Disfruta de descuentos exclusivos en nuestros productos más recientes.

  • Promociones y sorteos festivos: Participa en sorteos y promociones festivas.

👉 ¿Listo para explorar y crear con nosotros? Haz clic en [Aquí] y únete hoy mismo.

4.1.15 JUEGO - 10 Segundos

Introducción

A continuación, sigue mis instrucciones para crear un dispositivo de juego que pondrá a prueba tu concentración. Ata el interruptor de inclinación a un palo para hacer una varita mágica. Agita la varita, la pantalla de 4 dígitos comenzará a contar, agítala de nuevo para detener la cuenta. Si logras mantener el conteo en 10.00, entonces ganas. Puedes jugar con tus amigos para ver quién es el mago del tiempo.

Componentes necesarios

En este proyecto, necesitamos los siguientes componentes.

../_images/4.1.18_game_10_second_list.png

Es definitivamente conveniente comprar un kit completo, aquí está el enlace:

Nombre

ELEMENTOS EN ESTE KIT

ENLACE

Kit Raphael

337

Raphael Kit

También puedes comprarlos por separado en los enlaces a continuación.

INTRODUCCIÓN DEL COMPONENTE

ENLACE DE COMPRA

Placa de Extensión GPIO

COMPRAR

Protoboard

COMPRAR

Cables de Puente

COMPRAR

Resistor

COMPRAR

Pantalla de 7 segmentos y 4 dígitos

-

74HC595

COMPRAR

Interruptor de Inclinación

-

Diagrama esquemático

Nombre del T-Board

físico

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

Procedimientos experimentales

Paso 1: Construye el circuito.

../_images/4.1.18_game_10_second_circuit.png

Paso 2: Ve a la carpeta del código.

cd ~/raphael-kit/python-pi5

Paso 3: Ejecuta el archivo ejecutable.

sudo python3 4.1.18_GAME_10Second_zero.py

Agita la varita, la pantalla de 4 dígitos comenzará a contar, agítala de nuevo para detener la cuenta. Si logras mantener el conteo en 10.00, entonces ganas. Agítala una vez más para comenzar la siguiente ronda del juego.

Advertencia

Si recibe el mensaje de error RuntimeError: Cannot determine SOC peripheral base address, consulte Si «gpiozero» no funciona.

Código

Nota

Puedes Modificar/Restablecer/Copiar/Ejecutar/Detener el código a continuación. Pero antes de eso, necesitas ir a la ruta del código fuente como raphael-kit/python-pi5. Después de modificar el código, puedes ejecutarlo directamente para ver el efecto.

#!/usr/bin/env python3

from gpiozero import OutputDevice, Button
import time
import threading

# Inicializa el botón conectado al GPIO 26
sensorPin = Button(26)

# Define los pines GPIO conectados al registro de desplazamiento 74HC595
SDI = OutputDevice(24)   # Entrada de datos serial
RCLK = OutputDevice(23)  # Reloj de registro
SRCLK = OutputDevice(18) # Reloj de registro de desplazamiento

# Define los pines GPIO para la selección de dígitos en la pantalla de 7 segmentos
placePin = [OutputDevice(pin) para pin en (10, 22, 27, 17)]

# Define los códigos de segmentos para los números del 0 al 9 en la pantalla de 7 segmentos
number = (0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90)

# Variables del contador y del temporizador
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 y timer1 no es 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()

Explicación del Código

  1. El script comienza importando los módulos necesarios. La biblioteca gpiozero se utiliza para interactuar con dispositivos GPIO como botones, y los módulos time y threading pueden utilizarse para manejar tareas relacionadas con el tiempo u operaciones concurrentes.

    #!/usr/bin/env python3
    
    from gpiozero import OutputDevice, Button
    import time
    import threading
    
  2. Inicializa un objeto Button de la biblioteca GPIO Zero, conectándolo al pin GPIO 26. Esta configuración permite detectar las pulsaciones del botón.

    # Inicializa el botón conectado al GPIO 26
    sensorPin = Button(26)
    
  3. Inicializa los pines GPIO conectados a la entrada de datos en serie (SDI), la entrada del reloj de registro (RCLK) y la entrada del reloj del registro de desplazamiento (SRCLK) del registro de desplazamiento.

    # Define los pines GPIO conectados al registro de desplazamiento 74HC595
    SDI = OutputDevice(24)   # Entrada de datos serial
    RCLK = OutputDevice(23)  # Reloj de registro
    SRCLK = OutputDevice(18) # Reloj de registro de desplazamiento
    
  4. Inicializa los pines para cada dígito de la pantalla de 7 segmentos y define los códigos binarios para mostrar los números del 0 al 9.

    # Define los pines GPIO para la selección de dígitos en la pantalla de 7 segmentos
    placePin = [OutputDevice(pin) para pin en (10, 22, 27, 17)]
    
    # Define los códigos de segmentos para los números del 0 al 9 en la pantalla de 7 segmentos
    number = (0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90)
    
  5. Funciones para controlar la pantalla de 7 segmentos. clearDisplay apaga todos los segmentos, hc595_shift desplaza datos al registro de desplazamiento y pickDigit activa un dígito específico en la pantalla.

    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. Función para mostrar el valor actual del contador en la pantalla de 7 segmentos.

    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. Función para manejar los cambios de estado (inicio/detención) del contador basados en las pulsaciones del botón.

    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. Bucle principal que verifica continuamente el estado del botón y actualiza la pantalla. Llama a stateChange cuando el estado del botón 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. Función del temporizador que incrementa el contador a intervalos regulares (cada 0.01 segundo).

    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. Ejecuta el bucle principal y permite una salida limpia del programa utilizando una interrupción de teclado (Ctrl+C).

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