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 = 16 # 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), (192, 0, 0 )] # Player colors
pulse_count = 0 # For pulsing effect
pulse_is_on = False
last_pulse_time = 0
amount_of_players = 4
brightness = 1
button_pressed = False
button_press_start_time = 0
skip_player_pressed = False
# 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] * brightness), int(color[1] * brightness), int(color[2] * brightness))
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 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, skip_player_pressed
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
skip_player_pressed = False
elif not current_button_state and button_pressed: # Detect button released
time.sleep(0.05) # Debounce
button_pressed = False
if not skip_player_pressed:
if state == SHOW_COLOR:
start_timer()
elif state == RUNNING:
pause_timer()
elif state == PAUSED:
resume_timer()
elif state == IDLE:
show_current_player_color()
elif current_button_state and button_pressed and not skip_player_pressed: # Button is still being pressed
time.sleep(0.05) # Debounce
if time.ticks_ms() - button_press_start_time >= 2000: # Button held for 2 seconds
skip_player_pressed = True # Mark that we've triggered a skip
next_player() # Skip to the next player
def beep(duration=0.1):
#print("beep!") # turn on
buzzer.value(1)
time.sleep(duration) # Beep for 100 milliseconds
buzzer.value(0)
# turn off again
def beepOn():
buzzer.value(1)
time.sleep(0.1)
def beepOff():
buzzer.value(0)
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 - 1, -1, -1):
# Adjust color for 5% brightness
adjusted_color = (int(player_colors[i][0] * brightness), int(player_colors[i][1] * brightness), int(player_colors[i][2] * brightness))
np[j] = adjusted_color
np.write()
time.sleep(0.05)
time.sleep(0.05)
set_all_leds_color((0, 0, 0))
for i in range(3):
set_all_leds_color((0, 255, 0)) # Green
time.sleep(0.2)
set_all_leds_color((0, 0, 0)) # Off
time.sleep(0.1)
beep()
show_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, pulse_count, 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 * brightness), int(255 * brightness), int(0 * brightness)) # Green at 5% brightness
elif led_index > LED_COUNT / 4:
np[i] = (int(255 * brightness), int(140 * brightness), int(0 * brightness)) # Orange at 5% brightness
else:
np[i] = (int(255 * brightness), int(0 * brightness), int(0 * brightness)) # Red at 5% brightness
np.write()
if (led_index < 3):
beep()
else:
state = PULSING
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: # Faster pulse rate for the last LED, limit to 20 pulses
pulse_is_on = not pulse_is_on
# Adjust color for 5% brightness
adjusted_color = (int(255 * brightness), int(0 * brightness), int(0 * brightness))
np[0] = adjusted_color if pulse_is_on else (0, 0, 0) # Toggle the last LED
np.write()
last_pulse_time = time.ticks_ms()
pulse_count += 1
beepOn()
if pulse_count == 20:
np[0] = (0, 0, 0) # Ensure the last LED is off after pulsing
np.write()
beepOff()
#beep(0.5) # Beep to signal the end of the cycle
pulse_count = 0 # Reset pulse count for new cycle
pulse_is_on = False
last_pulse_time = 0
state = FINISHED # Mark the cycle as finished
def update_number_of_players():
global current_player, amount_of_players
pot_value = potentiometer.read() # Read the potentiometer value and map it to the number of players
if pot_value < 1024:
num_players = 1
elif pot_value < 2028:
num_players = 2
elif pot_value < 3072:
num_players = 3
else:
num_players = 4
if num_players != amount_of_players:
time.sleep(0.5)
current_player = 0
amount_of_players = num_players
if state != IDLE and state != ANIMATION:
show_current_player_color()
def setup():
update_number_of_players()
#show_current_player_color()
start_animation()
def loop():
check_button()
update_number_of_players()
if state == RUNNING and time.ticks_ms() - previous_millis >= interval:
update_timer()
if state == PULSING:
pulse_last_led()
if state == FINISHED:
next_player()
def main():
setup()
while True:
loop()
#time.sleep(0.1)
if __name__ == "__main__":
main()