from machine import Pin, ADC, Timer
import neopixel
import time
# Configuration
BUTTON_PIN = 14 # Button pin, make sure it's suitable for input
LED_PIN = 33 # LED strip pin, ensure this pin supports digital output
LED_COUNT = 24 # Number of LEDs in the strip
BUZZER_PIN = 12 # Buzzer pin, adjust if necessary and ensure it's suitable for output
POTENTIOMETER_PIN = 34 # Potentiometer pin, should be an ADC-capable pin
# State definitions
ANIMATION, IDLE, SHOW_COLOR, RUNNING, PAUSED, FINISHED, PULSING = range(7)
state = SHOW_COLOR # Initial state
previous_millis = 0 # For timing
interval = 1000 # Interval for actions, in milliseconds
current_player = 0 # Current player (if applicable)
led_index = LED_COUNT - 1 # For iterating LEDs, start from the last LED for anti-clockwise countdown
player_colors = [(255, 0, 255), (255, 255, 0), (0, 255, 255), (255, 255, 255)] # Player colors
pulse_count = 0 # For pulsing effect
pulse_is_on = False
last_pulse_time = 0
amount_of_players = 4
button_pressed = False
button_press_start_time = 0
# Initialize components
np = neopixel.NeoPixel(Pin(LED_PIN), LED_COUNT) # NeoPixel strip
button = Pin(BUTTON_PIN, Pin.IN, Pin.PULL_UP) # Button with internal pull-up
buzzer = Pin(BUZZER_PIN, Pin.OUT) # Buzzer as output
potentiometer = ADC(Pin(POTENTIOMETER_PIN)) # ADC object for potentiometer
potentiometer.atten(ADC.ATTN_11DB) # Configure ADC for a wider range
def set_all_leds_color(color):
# Adjust color for 5% brightness
adjusted_color = (int(color[0] * 0.05), int(color[1] * 0.05), int(color[2] * 0.05))
for i in range(LED_COUNT):
np[i] = adjusted_color
np.write() # Update the strip to show the change
def show_current_player_color():
global state, led_index
set_all_leds_color(player_colors[current_player])
led_index = LED_COUNT - 1 # Prepare for the countdown
state = SHOW_COLOR # Ensure we are in the correct state to start the timer
def start_timer():
global led_index, previous_millis, state
set_all_leds_color((0, 255, 0)) # Set all LEDs to green (5% brightness) for the countdown
led_index = LED_COUNT - 1
previous_millis = time.ticks_ms()
state = RUNNING
def pause_timer():
global state
state = PAUSED
def resume_timer():
global state, previous_millis
state = RUNNING
previous_millis = time.ticks_ms() # Reset timer to maintain correct timing
def check_button():
global button_pressed, button_press_start_time
current_button_state = not button.value()
if current_button_state and not button_pressed: # Detect button pressed
time.sleep(0.05) # Debounce
button_press_start_time = time.ticks_ms()
button_pressed = True
elif not current_button_state and button_pressed: # Detect button released
time.sleep(0.05) # Debounce
hold_time = time.ticks_ms() - button_press_start_time
button_pressed = False
if hold_time >= 2000 and state in [RUNNING, PAUSED, SHOW_COLOR]:
next_player()
else:
if state == SHOW_COLOR:
start_timer()
elif state == RUNNING:
pause_timer()
elif state == PAUSED:
resume_timer()
elif state == IDLE:
show_current_player_color()
def beep():
print("beep!") # turn on
time.sleep(0.1) # Beep for 100 milliseconds
# turn off again
def start_animation():
set_all_leds_color((0, 0, 0))
arr_size = len(player_colors)
for i in range(arr_size):
for j in range(LED_COUNT):
# Adjust color for 5% brightness
adjusted_color = (int(player_colors[i][0] * 0.05), int(player_colors[i][1] * 0.05), int(player_colors[i][2] * 0.05))
np[j] = adjusted_color
np.write()
time.sleep(0.05)
time.sleep(0.05)
set_all_leds_color((0, 0, 0)) # Turn off LEDs after the animation
for i in range(5):
set_all_leds_color((0, 255, 0)) # Flash green (5% brightness) for the start signal
time.sleep(0.1)
set_all_leds_color((0, 0, 0)) # Turn off LEDs
time.sleep(0.1)
beep() # Signal the end of the animation and the start of the game
show_current_player_color() # Show the current player color
def next_player():
global current_player
current_player = (current_player + 1) % amount_of_players # Cycle to the next player
show_current_player_color() # Initialize the next player turn
def update_timer():
global led_index, state, previous_millis
if led_index > 0:
np[led_index] = (0, 0, 0) # Turn off the current LED
led_index -= 1 # Move to the next LED for the next update
previous_millis = time.ticks_ms() # Reset the timer for the next update
for i in range(led_index + 1):
if led_index > LED_COUNT / 2:
np[i] = (int(0 * 0.05), int(255 * 0.05), int(0 * 0.05)) # Green at 5% brightness
elif led_index > LED_COUNT / 4:
np[i] = (int(255 * 0.05), int(165 * 0.05), int(0 * 0.05)) # Orange at 5% brightness
else:
np[i] = (int(255 * 0.05), int(0 * 0.05), int(0 * 0.05)) # Red at 5% brightness
np.write()
else:
state = PULSING # Change to pulsing state when countdown is done
previous_millis = time.ticks_ms()
def pulse_last_led():
global pulse_count, state, pulse_is_on, last_pulse_time
if time.ticks_ms() - last_pulse_time > 100 and pulse_count < 20: # Pulse the last LED
pulse_is_on = not pulse_is_on
np[0] = (int(255 * 0.05), 0, 0) if pulse_is_on else (0, 0, 0) # Red at 5% brightness
np.write()
last_pulse_time = time.ticks_ms()
pulse_count += 1
if pulse_count == 20:
state = FINISHED # Change to finished state after pulsing
pulse_count = 0 # Reset for the next cycle
pulse_is_on = False
last_pulse_time = 0
beep() # Signal the end
def update_number_of_players():
global current_player, amount_of_players
pot_value = potentiometer.read() # Read the potentiometer for the number of players
num_players = 1 if pot_value < 1024 else 2 if pot_value < 2048 else 3 if pot_value < 3072 else 4
if num_players != amount_of_players:
current_player = 0
amount_of_players = num_players
if state != IDLE and state != ANIMATION:
show_current_player_color()
def setup():
update_number_of_players()
start_animation() # Start the initial animation
def loop():
check_button()
update_number_of_players()
if state == RUNNING and time.ticks_ms() - previous_millis >= interval:
update_timer()
elif state == PULSING:
pulse_last_led()
elif state == FINISHED:
next_player()
def main():
setup()
while True:
loop()
if __name__ == "_main_":
main()