import board import rotaryio import neopixel import time import digitalio import microcontroller num_pixels = 10 pixels = neopixel.NeoPixel(board.GP5, num_pixels) encoder = rotaryio.IncrementalEncoder(board.GP19, board.GP18) button = digitalio.DigitalInOut(board.GP17) button.direction = digitalio.Direction.INPUT button.pull = digitalio.Pull.UP # Predefined colors colors = [ (255, 0, 0), # Red (0, 255, 0), # Green (0, 0, 255), # Blue (255, 255, 255), # White (200, 255, 200), # Cold white (255, 20, 100), # Warm white ] # Brightness levels (6 steps, including 0 for off) brightness_levels = [0.0, 0.2, 0.4, 0.6, 0.8, 1.0] # Check and initialize non-volatile memory if len(microcontroller.nvm) < 5: microcontroller.nvm = bytearray(5) # Initialize with 5 bytes microcontroller.nvm[0:4] = b"0.80" # Default brightness microcontroller.nvm[4:5] = (0).to_bytes(1, "little") # Default color index # Load settings from non-volatile memory try: brightness_index = int(float(microcontroller.nvm[0:4].decode()) * 5) color_index = int.from_bytes(microcontroller.nvm[4:5], "little") if color_index >= len(colors): color_index = 0 # Reset to default if out of range except ValueError: brightness_index = 4 # Default brightness (0.8) color_index = 0 # Default color index (red) pixels.brightness = brightness_levels[brightness_index] current_color = colors[color_index] pixels.fill(current_color) button_state = None last_encoder_pos = encoder.position def fade_colors(start_color, end_color, steps=50, delay=0.02): """Smoothly fade between two colors.""" for step in range(steps): ratio = step / steps interpolated_color = tuple( int(start_color[i] * (1 - ratio) + end_color[i] * ratio) for i in range(3) ) pixels.fill(interpolated_color) time.sleep(delay) while True: # Read encoder position for brightness control enc_pos = encoder.position if enc_pos != last_encoder_pos: step_change = enc_pos - last_encoder_pos last_encoder_pos = enc_pos brightness_index = min(max(brightness_index + step_change, 0), len(brightness_levels) - 1) pixels.brightness = brightness_levels[brightness_index] print(f"Brightness: {brightness_levels[brightness_index]:.2f}") # Handle button press to cycle colors if not button.value and button_state is None: button_state = "pressed" elif button.value and button_state == "pressed": new_color_index = (color_index + 1) % len(colors) fade_colors(colors[color_index], colors[new_color_index]) color_index = new_color_index current_color = colors[color_index] # Update current_color pixels.fill(current_color) # Apply the new color print(f"Selected color: {current_color}") button_state = None # Set the pixels to the current color (if not transitioning) if brightness_levels[brightness_index] > 0.0: # Only fill if brightness > 0 pixels.fill(current_color) # Save settings to non-volatile memory brightness_value = brightness_levels[brightness_index] microcontroller.nvm[0:4] = f"{brightness_value:.2f}".encode() microcontroller.nvm[4:5] = color_index.to_bytes(1, "little")