functioning start stop button
This commit is contained in:
230
random_timer.py
230
random_timer.py
@@ -1,87 +1,187 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
import time
|
|
||||||
import threading
|
|
||||||
import RPi.GPIO as GPIO
|
import RPi.GPIO as GPIO
|
||||||
|
import time
|
||||||
|
import random
|
||||||
|
import threading
|
||||||
from RPLCD.i2c import CharLCD
|
from RPLCD.i2c import CharLCD
|
||||||
|
|
||||||
# GPIO pin setup for buttons
|
# --- CONFIG ---
|
||||||
BUTTON_START_STOP = 17
|
WORDS_FILE = "words.txt"
|
||||||
|
TIMER_SECONDS = 30
|
||||||
|
I2C_ADDRESS = 0x27
|
||||||
|
I2C_CHIP = 'PCF8574'
|
||||||
|
|
||||||
|
# --- GPIO SETUP ---
|
||||||
|
GPIO.setmode(GPIO.BCM)
|
||||||
|
|
||||||
|
# Buttons mapped to pins
|
||||||
|
BUTTON_START_STOP = 23
|
||||||
BUTTON_NEXT = 27
|
BUTTON_NEXT = 27
|
||||||
BUTTON_TEAM1 = 22
|
BUTTON_TEAM1 = 22
|
||||||
|
BUTTON_TEAM2 = 17
|
||||||
|
|
||||||
GPIO.setmode(GPIO.BCM)
|
for btn_pin in (BUTTON_START_STOP, BUTTON_NEXT, BUTTON_TEAM1, BUTTON_TEAM2):
|
||||||
GPIO.setup(BUTTON_START_STOP, GPIO.IN, pull_up_down=GPIO.PUD_UP)
|
GPIO.setup(btn_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
|
||||||
GPIO.setup(BUTTON_NEXT, GPIO.IN, pull_up_down=GPIO.PUD_UP)
|
|
||||||
GPIO.setup(BUTTON_TEAM1, GPIO.IN, pull_up_down=GPIO.PUD_UP)
|
|
||||||
|
|
||||||
# LCD setup (adjust address and cols/rows if needed)
|
# --- LCD SETUP ---
|
||||||
lcd = CharLCD('PCF8574', 0x27)
|
lcd = CharLCD(I2C_CHIP, I2C_ADDRESS)
|
||||||
|
|
||||||
# Game variables
|
|
||||||
team1_score = 0
|
|
||||||
team2_score = 0
|
|
||||||
timer_running = False
|
|
||||||
timer_thread = None
|
|
||||||
seconds = 0
|
|
||||||
winner_displayed = False
|
|
||||||
|
|
||||||
# Timer function
|
|
||||||
def timer():
|
|
||||||
global seconds, timer_running
|
|
||||||
while timer_running:
|
|
||||||
seconds += 1
|
|
||||||
time.sleep(1)
|
|
||||||
|
|
||||||
def update_lcd():
|
|
||||||
global winner_displayed
|
|
||||||
lcd.clear()
|
lcd.clear()
|
||||||
if winner_displayed:
|
|
||||||
if team1_score >= 7:
|
|
||||||
lcd.write_string("Team 1 Wins!")
|
|
||||||
elif team2_score >= 7:
|
|
||||||
lcd.write_string("Team 2 Wins!")
|
|
||||||
else:
|
|
||||||
lcd.write_string(f"T1:{team1_score} T2:{team2_score}")
|
|
||||||
lcd.crlf()
|
|
||||||
lcd.write_string(f"Time: {seconds}s")
|
|
||||||
|
|
||||||
def start_stop_timer(channel):
|
# --- GLOBALS ---
|
||||||
|
words = []
|
||||||
|
timer_thread = None
|
||||||
|
timer_running = False
|
||||||
|
time_left = TIMER_SECONDS
|
||||||
|
score_t1 = 0
|
||||||
|
score_t2 = 0
|
||||||
|
current_word = ""
|
||||||
|
|
||||||
|
lock = threading.Lock() # Protect shared state
|
||||||
|
|
||||||
|
# --- LOAD WORDS ---
|
||||||
|
def load_words(path=WORDS_FILE):
|
||||||
|
try:
|
||||||
|
with open(path, "r", encoding="utf-8") as f:
|
||||||
|
lines = [line.strip() for line in f if line.strip()]
|
||||||
|
if not lines:
|
||||||
|
raise ValueError("Word file is empty.")
|
||||||
|
return lines
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Error loading words: {e}")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
# --- LCD HELPERS ---
|
||||||
|
def lcd_print_lines(line1="", line2=""):
|
||||||
|
lcd.clear()
|
||||||
|
lcd.cursor_pos = (0, 0)
|
||||||
|
lcd.write_string(line1.ljust(16)[:16])
|
||||||
|
lcd.cursor_pos = (1, 0)
|
||||||
|
lcd.write_string(line2.ljust(16)[:16])
|
||||||
|
|
||||||
|
def lcd_show_word_and_timer(word, seconds):
|
||||||
|
lcd.clear()
|
||||||
|
lcd.cursor_pos = (0, 0)
|
||||||
|
lcd.write_string(f"Time:{seconds:02d} ")
|
||||||
|
lcd.cursor_pos = (1, 0)
|
||||||
|
lcd.write_string(word.center(16))
|
||||||
|
|
||||||
|
def lcd_show_scores():
|
||||||
|
lcd.clear()
|
||||||
|
lcd.write_string(f"T1:{score_t1} T2:{score_t2}".center(16))
|
||||||
|
|
||||||
|
def lcd_show_winner(winner_team):
|
||||||
|
lcd.clear()
|
||||||
|
lcd.write_string(f"🏆 Team {winner_team} Wins!".center(16))
|
||||||
|
|
||||||
|
# --- TIMER THREAD ---
|
||||||
|
class CountdownTimer(threading.Thread):
|
||||||
|
def __init__(self, seconds):
|
||||||
|
super().__init__()
|
||||||
|
self.seconds = seconds
|
||||||
|
self._running = threading.Event()
|
||||||
|
self._running.set()
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
global time_left, timer_running
|
||||||
|
time_left = self.seconds
|
||||||
|
while time_left > 0 and self._running.is_set():
|
||||||
|
with lock:
|
||||||
|
lcd_show_word_and_timer(current_word, time_left)
|
||||||
|
time.sleep(1)
|
||||||
|
time_left -= 1
|
||||||
|
with lock:
|
||||||
|
timer_running = False
|
||||||
|
lcd_show_scores()
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
self._running.clear()
|
||||||
|
|
||||||
|
# --- GAME LOGIC ---
|
||||||
|
def pick_random_word():
|
||||||
|
global current_word
|
||||||
|
current_word = random.choice(words)
|
||||||
|
|
||||||
|
def start_stop_button_callback(channel):
|
||||||
|
print("Start Button Pressed")
|
||||||
global timer_running, timer_thread
|
global timer_running, timer_thread
|
||||||
if not timer_running:
|
with lock:
|
||||||
timer_running = True
|
if timer_running:
|
||||||
threading.Thread(target=timer, daemon=True).start()
|
# Stop timer
|
||||||
|
if timer_thread:
|
||||||
|
timer_thread.stop()
|
||||||
|
timer_thread.join()
|
||||||
|
timer_running = False
|
||||||
|
lcd_show_scores()
|
||||||
else:
|
else:
|
||||||
|
# Start timer & show first word
|
||||||
|
pick_random_word()
|
||||||
|
timer_thread = CountdownTimer(TIMER_SECONDS)
|
||||||
|
timer_thread.daemon = True
|
||||||
|
timer_running = True
|
||||||
|
timer_thread.start()
|
||||||
|
|
||||||
|
def next_button_callback(channel):
|
||||||
|
global current_word
|
||||||
|
with lock:
|
||||||
|
if timer_running:
|
||||||
|
pick_random_word()
|
||||||
|
|
||||||
|
def team1_button_callback(channel):
|
||||||
|
global score_t1
|
||||||
|
with lock:
|
||||||
|
if timer_running:
|
||||||
|
score_t1 += 1
|
||||||
|
if score_t1 >= 7:
|
||||||
timer_running = False
|
timer_running = False
|
||||||
|
lcd_show_winner(1)
|
||||||
|
reset_game_after_delay()
|
||||||
|
else:
|
||||||
|
lcd_show_scores()
|
||||||
|
|
||||||
def next_pressed(channel):
|
def team2_button_callback(channel):
|
||||||
global team1_score, team2_score, winner_displayed
|
global score_t2
|
||||||
if not winner_displayed:
|
with lock:
|
||||||
team2_score += 1
|
if timer_running:
|
||||||
check_winner()
|
score_t2 += 1
|
||||||
update_lcd()
|
if score_t2 >= 7:
|
||||||
|
|
||||||
def team1_pressed(channel):
|
|
||||||
global team1_score, winner_displayed
|
|
||||||
if not winner_displayed:
|
|
||||||
team1_score += 1
|
|
||||||
check_winner()
|
|
||||||
update_lcd()
|
|
||||||
|
|
||||||
def check_winner():
|
|
||||||
global winner_displayed, timer_running
|
|
||||||
if team1_score >= 7 or team2_score >= 7:
|
|
||||||
winner_displayed = True
|
|
||||||
timer_running = False
|
timer_running = False
|
||||||
|
lcd_show_winner(2)
|
||||||
|
reset_game_after_delay()
|
||||||
|
else:
|
||||||
|
lcd_show_scores()
|
||||||
|
|
||||||
# Attach button event listeners
|
def reset_game_after_delay(delay=5):
|
||||||
GPIO.add_event_detect(BUTTON_START_STOP, GPIO.FALLING, callback=start_stop_timer, bouncetime=300)
|
def reset():
|
||||||
GPIO.add_event_detect(BUTTON_NEXT, GPIO.FALLING, callback=next_pressed, bouncetime=300)
|
global score_t1, score_t2, current_word
|
||||||
GPIO.add_event_detect(BUTTON_TEAM1, GPIO.FALLING, callback=team1_pressed, bouncetime=300)
|
time.sleep(delay)
|
||||||
|
with lock:
|
||||||
|
score_t1 = 0
|
||||||
|
score_t2 = 0
|
||||||
|
current_word = ""
|
||||||
|
lcd_show_scores()
|
||||||
|
threading.Thread(target=reset, daemon=True).start()
|
||||||
|
|
||||||
|
# --- Setup GPIO event detection ---
|
||||||
|
GPIO.add_event_detect(BUTTON_START_STOP, GPIO.FALLING, callback=start_stop_button_callback, bouncetime=300)
|
||||||
|
GPIO.add_event_detect(BUTTON_NEXT, GPIO.FALLING, callback=next_button_callback, bouncetime=300)
|
||||||
|
GPIO.add_event_detect(BUTTON_TEAM1, GPIO.FALLING, callback=team1_button_callback, bouncetime=300)
|
||||||
|
GPIO.add_event_detect(BUTTON_TEAM2, GPIO.FALLING, callback=team2_button_callback, bouncetime=300)
|
||||||
|
|
||||||
|
# --- Main program ---
|
||||||
|
def main():
|
||||||
|
global words
|
||||||
|
words = load_words()
|
||||||
|
lcd_show_scores()
|
||||||
|
print("Catchphrase started! Use buttons to play.")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
while True:
|
while True:
|
||||||
update_lcd()
|
time.sleep(0.1)
|
||||||
time.sleep(0.5)
|
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
|
pass
|
||||||
|
finally:
|
||||||
GPIO.cleanup()
|
GPIO.cleanup()
|
||||||
lcd.clear()
|
lcd.clear()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|||||||
Reference in New Issue
Block a user