testing button functionality

This commit is contained in:
2025-08-11 20:11:32 -04:00
parent 66f64510f8
commit 79c92c23aa
2 changed files with 73 additions and 167 deletions

View File

@@ -0,0 +1,2 @@
start the virtual env with
source lcd-env/bin/activate

View File

@@ -1,183 +1,87 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
"""
Catchphrase with LCD Output (Scores & Reset)
"""
import random
import time import time
import threading import threading
import sys import RPi.GPIO as GPIO
from RPLCD.i2c import CharLCD from RPLCD.i2c import CharLCD
# ---------- CONFIG ---------- # GPIO pin setup for buttons
WORDS_FILE = "words.txt" # file with one word per line BUTTON_START_STOP = 17
TIMER_SECONDS = 30 # how long the timer runs BUTTON_NEXT = 27
I2C_ADDRESS = 0x27 # change if your LCD address is different BUTTON_TEAM1 = 22
I2C_CHIP = 'PCF8574' # common backpack chip
# ---------- LCD ---------- GPIO.setmode(GPIO.BCM)
lcd = CharLCD(I2C_CHIP, I2C_ADDRESS) GPIO.setup(BUTTON_START_STOP, 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)
def lcd_print(text, line=0): # LCD setup (adjust address and cols/rows if needed)
"""Print text centered on given LCD line (0 or 1), padded to clear leftovers.""" lcd = CharLCD('PCF8574', 0x27)
lcd.cursor_pos = (line, 0)
lcd.write_string(text.center(16))
def lcd_update_scores(): # Game variables
"""Update the bottom LCD line with team scores (T1 left, T2 right).""" team1_score = 0
lcd.cursor_pos = (1, 0) team2_score = 0
score_str = f"{score_t1}{' ' * 14}{score_t2}" timer_running = False
lcd.write_string(score_str) timer_thread = None
seconds = 0
winner_displayed = False
# ---------- HELPERS ---------- # Timer function
def load_words(path=WORDS_FILE): def timer():
try: global seconds, timer_running
with open(path, "r", encoding="utf-8") as f: while timer_running:
words = [line.strip() for line in f if line.strip()] seconds += 1
if not words: time.sleep(1)
raise ValueError("Word file is empty.")
return words
except Exception as e:
print(f"❌ Error loading words: {e}")
sys.exit(1)
def pick_random(words): def update_lcd():
return random.choice(words) global winner_displayed
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")
# ---------- TIMER THREAD ---------- def start_stop_timer(channel):
class CountdownTimer(threading.Thread): global timer_running, timer_thread
def __init__(self, seconds=TIMER_SECONDS, on_finish=None): if not timer_running:
super().__init__() timer_running = True
self.seconds = seconds threading.Thread(target=timer, daemon=True).start()
self.on_finish = on_finish else:
self._running = threading.Event() timer_running = False
self._running.set()
def run(self): def next_pressed(channel):
for _ in range(self.seconds): global team1_score, team2_score, winner_displayed
if not self._running.is_set(): if not winner_displayed:
break team2_score += 1
time.sleep(1) check_winner()
self._running.clear() update_lcd()
if self.on_finish:
self.on_finish()
def stop(self): def team1_pressed(channel):
self._running.clear() global team1_score, winner_displayed
if not winner_displayed:
team1_score += 1
check_winner()
update_lcd()
@property def check_winner():
def is_running(self): global winner_displayed, timer_running
return self._running.is_set() if team1_score >= 7 or team2_score >= 7:
winner_displayed = True
timer_running = False
# ---------- SCORE VARIABLES ---------- # Attach button event listeners
score_t1 = 0 GPIO.add_event_detect(BUTTON_START_STOP, GPIO.FALLING, callback=start_stop_timer, bouncetime=300)
score_t2 = 0 GPIO.add_event_detect(BUTTON_NEXT, GPIO.FALLING, callback=next_pressed, bouncetime=300)
GPIO.add_event_detect(BUTTON_TEAM1, GPIO.FALLING, callback=team1_pressed, bouncetime=300)
def add_score(team): try:
global score_t1, score_t2 while True:
if team == 1: update_lcd()
score_t1 += 1 time.sleep(0.5)
if score_t1 >= 7: except KeyboardInterrupt:
print("🏆 Team 1 wins! Scores reset.") GPIO.cleanup()
score_t1 = score_t2 = 0 lcd.clear()
elif team == 2:
score_t2 += 1
if score_t2 >= 7:
print("🏆 Team 2 wins! Scores reset.")
score_t1 = score_t2 = 0
lcd_update_scores()
def reset_scores():
global score_t1, score_t2
score_t1 = score_t2 = 0
lcd_update_scores()
# ---------- MAIN LOOP ----------
def main():
global score_t1, score_t2
words = load_words()
timer_thread = None
print("=== Catchphrase, with LCD & Scores ===")
print("Commands:")
print(" start - start 30s timer & show a word")
print(" next - show another word while timer runs")
print(" stop - stop timer early")
print(" t1 - add point to Team 1")
print(" t2 - add point to Team 2")
print(" reset - reset both scores to 0")
print(" exit / quit - leave the program")
lcd_print("Ready", line=0)
lcd_update_scores()
def announce_finish():
print("\n⏰ Time is up! Returning to menu.")
lcd_print("Time is up!", line=0)
lcd_update_scores()
while True:
try:
cmd = input("\n> ").strip().lower()
except EOFError:
break
if cmd in ("exit", "quit"):
if timer_thread and timer_thread.is_running:
timer_thread.stop()
timer_thread.join()
lcd_print("Goodbye!", line=0)
lcd_update_scores()
print("👋 Goodbye!")
break
elif cmd == "start":
if timer_thread and timer_thread.is_running:
print("[!] Timer is already running.")
else:
timer_thread = CountdownTimer(on_finish=announce_finish)
timer_thread.daemon = True
timer_thread.start()
word = pick_random(words)
print(word)
lcd_print(word, line=0)
lcd_update_scores()
print(f"[+] 30-second timer started. ({TIMER_SECONDS}s)")
elif cmd == "next":
if not (timer_thread and timer_thread.is_running):
print("[!] No active timer - use 'start' first.")
else:
word = pick_random(words)
print(word)
lcd_print(word, line=0)
lcd_update_scores()
elif cmd == "stop":
if timer_thread and timer_thread.is_running:
timer_thread.stop()
timer_thread.join()
lcd_print("Stopped early", line=0)
lcd_update_scores()
print("[+] Timer stopped early.")
else:
print("[!] There is no running timer to stop.")
elif cmd == "t1":
add_score(1)
print(f"Team 1: {score_t1}, Team 2: {score_t2}")
elif cmd == "t2":
add_score(2)
print(f"Team 1: {score_t1}, Team 2: {score_t2}")
elif cmd == "reset":
reset_scores()
print("Scores reset.")
else:
print(f"[!] Unknown command: {cmd}")
if __name__ == "__main__":
main()