Madison Nasteff
Published © GPL3+

Racing Game

Race the clock in this game of chasing LEDs!

IntermediateShowcase (no instructions)5 hours1,152
Racing Game

Things used in this project

Hardware components

PocketBeagle
BeagleBoard.org PocketBeagle
×1
Rotary potentiometer (generic)
Rotary potentiometer (generic)
×1
Jumper wires (generic)
Jumper wires (generic)
×20
Breadboard (generic)
Breadboard (generic)
×1
LED (generic)
LED (generic)
×8
Push Button (generic)
×1
Resistor 1k ohm
Resistor 1k ohm
×10
SN74LS164N Shift Regsiter
×1

Story

Read more

Schematics

Fritzing Diagram

beerbike_bb_9u2jdfhftb_KimhTDYo5y.jpg

Code

Beer Bike Racing Game

Python
"""
--------------------------------------------------------------------------
PocketBeagle LED Racing Beer Bike Game
--------------------------------------------------------------------------
License:   
Copyright 2017

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------
"""

# Peripheral path
GPIO_BASE_PATH               = "/sys/class/gpio"
ADC_BASE_PATH                = "/sys/bus/iio/devices/iio:device0"

# GPIO direction
IN                           = True
OUT                          = False

# GPIO output state
LOW                          = "0"
HIGH                         = "1"

# LEDs GPIO values
CLEAR                         = (1, 27)           # gpio59
CLOCK                         = (1, 26)           # gpio58
DATA                          = (0, 26)           # gpio26
BUTTON0                       = (1, 12)           # gpio44

# count variable
COUNT                         = 0

# HT16K33 values
DISPLAY_I2C_BUS              = 1                 # I2C 1  
DISPLAY_I2C_ADDR             = 0x70
DISPLAY_CMD                  = "i2cset -y 1 0x70" 


# ADC voltage range
min_adc_voltage              = 0
max_adc_voltage              = 1.65

# ------------------------------------------------------------------------
# Display Library
# ------------------------------------------------------------------------
import os
import Adafruit_BBIO.ADC as ADC
ADC.setup()

HEX_DIGITS                  = [0x3f, 0x06, 0x5b, 0x4f,    # 0, 1, 2, 3
                               0x66, 0x6d, 0x7d, 0x07,    # 4, 5, 6, 7
                               0x7f, 0x6f, 0x77, 0x7c,    # 8, 9, A, b
                               0x39, 0x5e, 0x79, 0x71]    # C, d, E, F

CLEAR_DIGIT                 = 0x7F
POINT_VALUE                 = 0x80

DIGIT_ADDR                  = [0x00, 0x02, 0x06, 0x08]
COLON_ADDR                  = 0x04
                      
HT16K33_BLINK_CMD           = 0x80
HT16K33_BLINK_DISPLAYON     = 0x01
HT16K33_BLINK_OFF           = 0x00
HT16K33_BLINK_2HZ           = 0x02
HT16K33_BLINK_1HZ           = 0x04
HT16K33_BLINK_HALFHZ        = 0x06

HT16K33_SYSTEM_SETUP        = 0x20
HT16K33_OSCILLATOR          = 0x01

HT16K33_BRIGHTNESS_CMD      = 0xE0
HT16K33_BRIGHTNESS_HIGHEST  = 0x0F
HT16K33_BRIGHTNESS_DARKEST  = 0x00


def display_setup():
    """Setup display"""
    # i2cset -y 0 0x70 0x21
    os.system("{0} {1}".format(DISPLAY_CMD, (HT16K33_SYSTEM_SETUP | HT16K33_OSCILLATOR)))
    # i2cset -y 0 0x70 0x81
    os.system("{0} {1}".format(DISPLAY_CMD, (HT16K33_BLINK_CMD | HT16K33_BLINK_OFF | HT16K33_BLINK_DISPLAYON)))
    # i2cset -y 0 0x70 0xEF
    os.system("{0} {1}".format(DISPLAY_CMD, (HT16K33_BRIGHTNESS_CMD | HT16K33_BRIGHTNESS_HIGHEST)))

# End def

def display_clear():
    """Clear the display to read '0000'"""
    # i2cset -y 0 0x70 0x00 0x3F
    os.system("{0} {1} {2}".format(DISPLAY_CMD, DIGIT_ADDR[0], HEX_DIGITS[0]))
    # i2cset -y 0 0x70 0x02 0x3F
    os.system("{0} {1} {2}".format(DISPLAY_CMD, DIGIT_ADDR[1], HEX_DIGITS[0]))
    # i2cset -y 0 0x70 0x06 0x3F
    os.system("{0} {1} {2}".format(DISPLAY_CMD, DIGIT_ADDR[2], HEX_DIGITS[0]))
    # i2cset -y 0 0x70 0x08 0x3F
    os.system("{0} {1} {2}".format(DISPLAY_CMD, DIGIT_ADDR[3], HEX_DIGITS[0]))
    
    os.system("{0} {1} {2}".format(DISPLAY_CMD, COLON_ADDR, 0x0))
    
# End def


def display_set(data):
    """Display the data."""

    for i in range(0,3):
        display_set_digit(i, data[i])
    
# End def


def display_set_digit(digit_number, data, double_point=False):
    """Update the given digit of the display."""
    os.system("{0} {1} {2}".format(DISPLAY_CMD, DIGIT_ADDR[digit_number], display_encode(data, double_point)))    

# End def


def display_encode(data, double_point=False):
    """Encode data to TM1637 format."""
    ret_val = 0
    
    if (data != CLEAR_DIGIT):
        if double_point:
            ret_val = HEX_DIGITS[data] + POINT_VALUE
        else:
            ret_val = HEX_DIGITS[data]

    return ret_val

# End def


# ------------------------------------------------------------------------
# GPIO / ADC access library
# ------------------------------------------------------------------------
import os
import time

def gpio_setup(gpio, direction, default_value=False):
    """Setup GPIO pin
    
      * Test if GPIO exists; if not create it
      * Set direction
      * Set default value
    """
    gpio_number = str((gpio[0] * 32) + gpio[1])
    path        = "{0}/gpio{1}".format(GPIO_BASE_PATH, gpio_number)
    
    if not os.path.exists(path):
        # "echo {gpio_number} > {GPIO_BASE_PATH}/export"
        print("Create GPIO: {0}".format(gpio_number))
        with open("{0}/export".format(GPIO_BASE_PATH), 'w') as f:
            f.write(gpio_number)
    
    if direction:
        # "echo in > {path}/direction"
        with open("{0}/direction".format(path), 'w') as f:
            f.write("in")
    else:
        # "echo out > {path}/direction"
        with open("{0}/direction".format(path), 'w') as f:
            f.write("out")
        
    if default_value:
        # "echo {default_value} > {path}/value"
        with open("{0}/value".format(path), 'w') as f:
            f.write(default_value)
    
# End def


def gpio_set(gpio, value):
    """Set GPIO ouptut value."""
    gpio_number = str((gpio[0] * 32) + gpio[1])
    path        = "{0}/gpio{1}".format(GPIO_BASE_PATH, gpio_number)
    
    # "echo {value} > {path}/value"
    with open("{0}/value".format(path), 'w') as f:
        f.write(value)

# End def


def gpio_get(gpio):
    """Get GPIO input value."""
    gpio_number = str((gpio[0] * 32) + gpio[1])
    path        = "{0}/gpio{1}".format(GPIO_BASE_PATH, gpio_number)
    
    # "cat {path}/value"
    with open("{0}/value".format(path), 'r') as f:
        out = f.read()
    
    return float(out)

# End def

# ------------------------------------------------------------------------
# Setup
# ------------------------------------------------------------------------
gpio_setup(CLEAR,OUT)
gpio_setup(DATA,OUT)
gpio_setup(CLOCK,OUT)
gpio_setup(BUTTON0, IN)
display_setup()


# ------------------------------------------------------------------------
# setshift function
# Set LED value script
# Takes input of 8 bites (1 or 0)
# and will shift that into register
# ------------------------------------------------------------------------
def setshift(shift):
    
    gpio_set(CLEAR,LOW)
    gpio_set(DATA,LOW)
    
    gpio_set(CLEAR,HIGH)
    
    for i in shift:
        gpio_set(CLOCK,LOW)
        time.sleep(0.00001)
        if i == 0:
            gpio_set(DATA,LOW)
        else:
            gpio_set(DATA,HIGH)
        gpio_set(CLOCK,HIGH)
        time.sleep(0.0001)
        
    gpio_set(CLOCK,LOW)
    
    answer = gpio_get(BUTTON0)
# End def

# ------------------------------------------------------------------------
# Set display to value
# ------------------------------------------------------------------------
def update_display(value):
    """Update the value on the display."""
    
    # print("Score = {0}".format(value))    
    
    if (value == 0):
        display_clear()
    else:
        if (value < 10):
            display_set_digit(3, value)
        else:
            if (value < 100):
                display_set_digit(3, (value % 10))
                display_set_digit(2, (value / 10))
            else:
                if (value < 1000):
                    display_set_digit(3, (value % 10))
                    display_set_digit(2, ((value / 10) % 10))
                    display_set_digit(1, (value / 100), True)
                else:
                    if (value < 10000):
                        display_set_digit(3, (value % 10))
                        display_set_digit(2, ((value / 10) % 10))
                        display_set_digit(1, ((value / 100) % 10),True)
                        display_set_digit(0, (value / 1000))
                    else:
                        print ("Value too big to display.")
        
# End def

# Reset display
update_display(0)


# Set difficulty

from time import sleep
analogPin="P9_33"
print("Twist knob to select difficulty")
potValcurrent = 0
difficulty = 0
while gpio_get(BUTTON0) == 0:
    time.sleep(.5)
    potVal=ADC.read(analogPin)
    if potVal > 0.15 and potVal < .225 and difficulty != 1:
        difficulty = 1
        setshift(map(int,str(10000000)))
    elif potVal > 0.225 and potVal < .3 and difficulty != 2:
        difficulty = 2
        setshift(map(int,str(11000000)))
    elif potVal > 0.3 and potVal < .375 and difficulty != 3:
        difficulty = 3
        setshift(map(int,str(11100000)))
    elif potVal > 0.375 and potVal < .43 and difficulty != 4:
        difficulty = 4
        setshift(map(int,str(11110000)))
    elif potVal > 0.43 and potVal < .48 and difficulty != 5:
        difficulty = 5
        setshift(map(int,str(11111000)))
    elif potVal > 0.48 and potVal < .52 and difficulty != 6:
        difficulty = 6
        setshift(map(int,str(11111100)))
    elif potVal > 0.52 and potVal < .60 and difficulty != 7:
        difficulty = 7
        setshift(map(int,str(11111110)))
    elif potVal > 0.60 and difficulty != 8:
        difficulty = 8
        setshift(map(int,str(11111111)))
    else:
        pass


setshift(map(int,str(00000000)))
print("Difficulty = " + str(difficulty))

# begin game
print("Game beginning in")
update_display(3)
time.sleep(1)
update_display(2)
time.sleep(1)
update_display(1)
time.sleep(1)

# initial LED on
setshift(map(int,str(00000000)))
setshift(map(int,str(00000001)))

# start timer
start = time.time()
update_display(int(start-time.time()))

# gameplay
for i in range(0,8*difficulty):
    while gpio_get(BUTTON0) == 0:
        update_display((int(100*round(time.time()-start,2))))
    COUNT += 1
    if COUNT == difficulty:
    #if COUNT == 5:
        update_display((int(100*round(time.time()-start,2))))
        gpio_set(CLOCK,LOW)
        time.sleep(0.00001)
        gpio_set(DATA,LOW)
        gpio_set(CLOCK,HIGH)
        time.sleep(0.0001)
        COUNT = 0
    while gpio_get(BUTTON0):
        pass

end = time.time()
update_display((int(100*round(time.time()-start,2))))

print(end - start)

Credits

Madison Nasteff

Madison Nasteff

2 projects • 0 followers
Rice University Mechanical Engineering Student

Comments