import machine
import time
# Pin Assignments (Adjusted for Wokwi Simulator)
RING_LED_PINS = [11, 12, 13, 14, 15, 16, 17, 18]
COCKPIT_LED_PIN = 19
ENGINE_LED_PIN = 20
BUTTON_PIN = 10
# Configuration
ENGINE_LIGHT_ENABLED = True
# Initialize GPIO pins
button_pin = machine.Pin(BUTTON_PIN, machine.Pin.IN)
# Set PWM objects
ring_pwms = [machine.PWM(machine.Pin(pin)) for pin in RING_LED_PINS]
cockpit_pwm = machine.PWM(machine.Pin(COCKPIT_LED_PIN))
if ENGINE_LIGHT_ENABLED:
engine_pwm = machine.PWM(machine.Pin(ENGINE_LED_PIN))
# Set PWM frequency
for pwm in ring_pwms:
pwm.freq(100) # 1 kHz frequency
cockpit_pwm.freq(100)
if ENGINE_LIGHT_ENABLED:
engine_pwm.freq(100)
# Lighting mode variables
ring_mode = 0
cockpit_mode = 0
engine_mode = 0
breathe_brightness = 100
breathe_direction = 1
flicker_brightness = 0
chase_position = 0
chase_direction = 1
chase_speed = 50 # Lower values increase speed (in ms)
swim_position = 0
swim_direction = 1
swim_speed = 20
# Lighting modes
def ring_on():
for pin in RING_LED_PINS:
machine.Pin(pin, machine.Pin.OUT).value(1)
def ring_breathe():
global breathe_brightness, breathe_direction
if breathe_direction == 1:
breathe_brightness += 2 # Smaller step size to slow down changes
if breathe_brightness > 255:
breathe_brightness = 255
breathe_direction = -1
else:
breathe_brightness -= 2
if breathe_brightness < 50:
breathe_brightness = 50
breathe_direction = 1
# Convert brightness (0-255) to duty cycle (0-65535)
duty_value = int((breathe_brightness / 255) * 65535)
print(f"Setting duty_u16 to: {duty_value}")
# Set PWM values for each LED pin
for pwm in ring_pwms:
pwm.duty_u16(duty_value)
time.sleep(0.05) # Add a small delay to slow down the breathing effect (50ms)
def ring_chase():
global chase_position, chase_direction
# Calculate LED brightness values
for i, pwm in enumerate(ring_pwms):
distance = abs(i - chase_position)
brightness = 255 - (distance * 50) # This may need adjusting if 50 is too high
if brightness < 0:
brightness = 0
# Convert brightness (0-255) to duty cycle (0-65535)
duty_value = int((brightness / 255) * 65535)
pwm.duty_u16(duty_value)
# Update chase position
chase_position += chase_direction
if chase_position == len(RING_LED_PINS) - 1:
chase_direction = -1
elif chase_position == 0:
chase_direction = 1
# Delay for chase speed
time.sleep_ms(chase_speed)
def ring_chase_fast():
global chase_speed
chase_speed = 50 # Fast speed
ring_chase()
def ring_chase_slow():
global chase_speed
chase_speed = 100 # Slow speed
ring_chase()
def ring_swim():
global swim_position, swim_direction
# Calculate LED brightness values
for i, pwm in enumerate(ring_pwms):
distance = abs(i - swim_position)
brightness = 255 - (distance * 30)
if brightness < 0:
brightness = 0
duty_value = int((brightness / 255) * 65535)
pwm.duty_u16(duty_value)
# Additional swim positions
distance2 = abs(i - (swim_position + 5))
brightness2 = 255 - (distance2 * 30)
if brightness2 < 0:
brightness2 = 0
duty_value = int((breathe_brightness / 255) * 65535)
pwm.duty_u16(min(brightness, brightness2))
# Update swim position
swim_position += swim_direction
if swim_position == len(RING_LED_PINS) - 1:
swim_direction = -1
elif swim_position == 0:
swim_direction = 1
# Delay for swim speed
time.sleep_ms(swim_speed)
def ring_off():
for pin in RING_LED_PINS:
machine.Pin(pin, machine.Pin.OUT).value(0)
ring_modes = [
ring_on,
ring_off,
ring_breathe,
ring_chase_fast,
ring_chase_slow,
ring_swim
]
ring_mode_names = ["On", "Off", "Breathe", "Chase Fast", "Chase Slow", "Swim"]
def cockpit_off():
machine.Pin(COCKPIT_LED_PIN, machine.Pin.OUT).value(0)
def cockpit_on():
machine.Pin(COCKPIT_LED_PIN, machine.Pin.OUT).value(1)
def cockpit_breathe():
global breathe_brightness, breathe_direction
if breathe_direction == 1:
breathe_brightness += 5
if breathe_brightness > 255:
breathe_brightness = 255
breathe_direction = -1
else:
breathe_brightness -= 5
if breathe_brightness < 50:
breathe_brightness = 50
breathe_direction = 1
duty_value = int((breathe_brightness / 255) * 65535)
cockpit_pwm.duty_u16(breathe_brightness)
def cockpit_flicker():
global flicker_brightness
flicker_brightness = random.randint(50, 200)
duty_value = int((breathe_brightness / 255) * 65535)
cockpit_pwm.duty_u16(flicker_brightness)
cockpit_modes = [cockpit_off, cockpit_on, cockpit_breathe, cockpit_flicker]
cockpit_mode_names = ["Off", "On", "Breathe", "Flicker"]
def engine_off():
machine.Pin(ENGINE_LED_PIN, machine.Pin.OUT).value(0)
def engine_on():
machine.Pin(ENGINE_LED_PIN, machine.Pin.OUT).value(1)
def engine_flicker():
# TODO: Implement engine flicker logic
pass
engine_modes = [engine_off, engine_on, engine_flicker]
engine_mode_names = ["Off", "On", "Flicker"]
# Debouncing and tap detection variables
button_state = 1 # Start with the button unpressed (1)
last_button_state = 1 # Previous button state
last_debounce_time = time.ticks_ms() # Last time the button state changed
debounce_delay = 100 # Increase debounce delay to 100ms
tap_count = 0 # Count of taps
last_tap_time = time.ticks_ms() # Last time a tap was detected
tap_threshold = 500 # Increase tap threshold to 500ms for double/triple tap detection
button_pressed = False # To track button press state
# Adjust debounce delay and tap threshold for better tap detection
debounce_delay = 100 # Increase debounce delay to 100ms
tap_threshold = 500 # Increase tap threshold to 500ms for double/triple tap detection
button_pressed = False # To track button state
# Function to read and debounce button presses
def button_read():
global button_pressed, last_debounce_time, button_state, last_button_state
current_time = time.ticks_ms()
if button_pin.value() != last_button_state: # Check for state change
last_debounce_time = current_time # Reset debounce time
if (current_time - last_debounce_time) > debounce_delay: # Check debounce delay
if button_pin.value() != button_state: # State has changed
button_state = button_pin.value()
if button_state == 0: # Button pressed
button_pressed = True
else: # Button released
button_pressed = False
last_button_state = button_pin.value()
return button_pressed
# Function to detect taps
def tap_detect():
global tap_count, last_tap_time, button_pressed
current_time = time.ticks_ms()
if button_read(): # Button is pressed
if current_time - last_tap_time < tap_threshold: # Within threshold
tap_count += 1
else:
tap_count = 1 # Reset to 1 if outside threshold
last_tap_time = current_time
elif not button_read() and tap_count > 0: # Button released, process tap
if tap_count == 1:
print("Single Tap Detected")
elif tap_count == 2:
print("Double Tap Detected")
elif tap_count == 3:
print("Triple Tap Detected")
tap_count = 0 # Reset tap count
return tap_count
# Main loop
while True:
tap_count = tap_detect()
if tap_count > 0: # Check for taps
if tap_count == 1: # Single tap: change ring mode
ring_mode = (ring_mode + 1) % len(ring_modes)
ring_modes[ring_mode]()
print(f"Ring Mode: {ring_mode_names[ring_mode]}")
elif tap_count == 2: # Double tap: change cockpit mode
cockpit_mode = (cockpit_mode + 1) % len(cockpit_modes)
cockpit_modes[cockpit_mode]()
print(f"Cockpit Mode: {cockpit_mode_names[cockpit_mode]}")
elif tap_count == 3 and ENGINE_LIGHT_ENABLED: # Triple tap: change engine mode
engine_mode = (engine_mode + 1) % len(engine_modes)
engine_modes[engine_mode]()
print(f"Engine Mode: {engine_mode_names[engine_mode]}")
# Update lighting states
ring_modes[ring_mode]()
cockpit_modes[cockpit_mode]()
if ENGINE_LIGHT_ENABLED:
engine_modes[engine_mode]()
time.sleep(0.01) # Short delay