import RPi.GPIO as GPIO
import time
import threading
# Define GPIO pin numbers
SER = 23
SRCLK = 25
RCLK = 24
SRCLR = 12
DIGIT_PINS = [5, 6, 13,16]
# Define bit patterns for numbers 0 to 9
PATTERNS = [0xfc, 0x60, 0xda, 0xf2, 0x66, 0xb6, 0xbe, 0xe0, 0xfe, 0xf6]
# Define initializing function
def initialize():
GPIO.setmode(GPIO.BCM)
# Deselect all the digits
for digit in DIGIT_PINS:
GPIO.setup(digit, GPIO.OUT, initial=GPIO.LOW)
# LEDs are anode common
GPIO.setup(SER, GPIO.OUT, initial=GPIO.HIGH)
GPIO.setup(SRCLK, GPIO.OUT, initial=GPIO.LOW)
GPIO.setup(RCLK, GPIO.OUT, initial=GPIO.LOW)
# SRCLR is negative logic
GPIO.setup(SRCLR, GPIO.OUT, initial=GPIO.HIGH)
# Define ending process function
def destroy():
for digit in DIGIT_PINS:
GPIO.output(digit, GPIO.LOW)
GPIO.cleanup()
# Define function to display single digit
# digit: suffixes of DIGITS list
# pattern_number: suffixes of PATTERNS list
# duration: Duration time to turn on the designated digit (milliseconds)
def display_a_digit(digit, pattern_number, duration):
GPIO.output(DIGIT_PINS[digit], GPIO.HIGH)
# Do for each number display
for n in range(8):
# Input bits from LSB to MSB
# True == 1 == GPIO.HIGH and False == 0 == GPIO.LOW
GPIO.output(SER, not((PATTERNS[pattern_number] >> n) & 1))
# Send bit to shift register
GPIO.output(SRCLK, GPIO.HIGH)
GPIO.output(SRCLK, GPIO.LOW)
# Get parallel data
GPIO.output(RCLK, GPIO.HIGH)
GPIO.output(RCLK, GPIO.LOW)
# Continue to turn on during duration time
time.sleep(duration)
# Turn off the digit afterwards
GPIO.output(DIGIT_PINS[digit], GPIO.LOW)
# Display all the digits
# value_string: 4-digit integer value in string to display
# duration: duration time to display each digit
def display_digits(value_string, duration):
for digit, number in enumerate(list(value_string)):
display_a_digit(digit, int(number), duration)
# Define function to convert integer to 2-digit string with 0 prefixed
def get_two_digits(n):
return ('00' + str(n))[-2:]
# Define custom class inheriting Thread to display number
class NumberDisplay(threading.Thread):
# Arguments are same to those of display_digits function
def __init__(self, value_string, duration):
threading.Thread.__init__(self)
self.value_string = value_string
self.duration = duration
self.is_running = True
# Override run method of Thread class
def run(self):
# Continue while the flag is True
while self.is_running:
display_digits(self.value_string, self.duration)
# Quit running by setting the flag to False
def stop(self):
self.is_running = False
# Start Execution
initialize()
# time is counted in seconds
minutes = 0
seconds = 5
time_in_seconds = minutes * 60 + seconds
try:
# Loop while time remains
while time_in_seconds > 0:
# Set value_string from minuts and seconds
m = time_in_seconds // 60
s = time_in_seconds - m * 60
value_string = get_two_digits(m) + get_two_digits(s)
# Create thread to display the number
t = NumberDisplay(value_string, 0.001)
# Continue to display for 1 second
t.start()
time.sleep(1.0)
t.stop()
# Count down
time_in_seconds -= 1
while True:
display_digits('0000', 0.001)
except KeyboardInterrupt:
destroy()