# https://wokwi.com/projects/392220419950952449
from machine import Pin, PWM
from time import sleep_ms
import neopixel
import machine
import utime
# Define the frequencies for each note (in Hz)
NOTE_C4 = 261
NOTE_D4 = 294
NOTE_E4 = 329
NOTE_F4 = 349
NOTE_G4 = 392
NOTE_A4 = 440
NOTE_B4 = 494
NOTE_C5 = 523
# Define the durations for each note (in milliseconds)
DURATION_QUARTER = 250
DURATION_HALF = 500
DURATION_WHOLE = 1000
# Define the pin for sound output
SOUND_PIN = 22
# Define the pin for NeoPixel
NEOPIXEL_PIN = 23
NUM_PIXELS = 256
def play_tune(frequency, duration):
"""
Play a single note.
"""
pwm.freq(frequency)
pwm.duty(512) # 50% duty cycle
sleep_ms(duration)
pwm.duty(0) # Turn off the sound
sleep_ms(50) # Add a small delay to distinguish between consecutive notes
def play_tunes(tunes, durations):
"""
Play a sequence of notes with specified durations.
"""
for tune, duration in zip(tunes, durations):
play_tune(tune, duration)
def display_reducing_square():
"""
Display a reducing square animation on NeoPixel.
"""
for size in range(16, 1, -8):
rainbow_square(size)
pixels.write()
utime.sleep(1)
def rainbow_square(size):
"""
Fill NeoPixel with a rainbow-colored square of specified size.
"""
for i in range(size):
color = wheel((i * 256 // size) & 255)
# Fill top row
for col in range(i, size):
pixels[i * 16 + col] = color
# Fill bottom row
for col in range(i, size):
pixels[(size - 1) * 16 + col] = color
# Fill left column
for row in range(i + 1, size - 1):
pixels[row * 16 + i] = color
# Fill right column
for row in range(i + 1, size - 1):
pixels[row * 16 + size - 1] = color
def wheel(wheel_pos):
"""
Generate a color based on a position in a color wheel.
"""
wheel_pos = 255 - wheel_pos
if wheel_pos < 85:
return (255 - wheel_pos * 3, 0, wheel_pos * 3)
if wheel_pos < 170:
wheel_pos -= 85
return (0, wheel_pos * 3, 255 - wheel_pos * 3)
wheel_pos -= 170
return (wheel_pos * 3, 255 - wheel_pos * 3, 0)
# Define musical tunes and their durations
tunes_list = [
([NOTE_C4, NOTE_D4, NOTE_E4, NOTE_F4, NOTE_G4, NOTE_A4, NOTE_B4, NOTE_C5], [DURATION_QUARTER] * 8),
([NOTE_E4, NOTE_D4, NOTE_C4, NOTE_D4, NOTE_E4, NOTE_E4, NOTE_E4, NOTE_D4, NOTE_D4, NOTE_D4, NOTE_E4, NOTE_E4, NOTE_E4, NOTE_E4, NOTE_D4, NOTE_D4, NOTE_C4, NOTE_D4, NOTE_E4, NOTE_E4, NOTE_E4, NOTE_E4, NOTE_D4, NOTE_D4, NOTE_E4, NOTE_D4, NOTE_C4], [DURATION_QUARTER] * 14 + [DURATION_HALF] * 2),
([NOTE_C4, NOTE_E4, NOTE_G4, NOTE_A4, NOTE_G4, NOTE_E4, NOTE_C4], [DURATION_HALF] * 7),
([NOTE_E4, NOTE_G4, NOTE_F4, NOTE_C4, NOTE_D4, NOTE_A4, NOTE_B4, NOTE_E4], [DURATION_QUARTER] * 8 + [DURATION_WHOLE]),
([NOTE_C4, NOTE_D4, NOTE_E4, NOTE_F4, NOTE_G4, NOTE_A4, NOTE_B4, NOTE_C5], [DURATION_HALF] * 8),
([NOTE_E4, NOTE_A4, NOTE_C4, NOTE_B4, NOTE_G4, NOTE_D4, NOTE_E4, NOTE_F4] + [NOTE_C4, NOTE_D4, NOTE_E4, NOTE_F4, NOTE_G4, NOTE_A4, NOTE_B4, NOTE_C5], [DURATION_QUARTER] * 8 + [DURATION_QUARTER] * 7 + [DURATION_WHOLE])
]
# Initialize NeoPixel strip
pixels = neopixel.NeoPixel(machine.Pin(NEOPIXEL_PIN), NUM_PIXELS)
# Initialize PWM for sound
pwm = PWM(Pin(SOUND_PIN))
# Play tunes and display animation
for tunes, durations in tunes_list:
play_tunes(tunes, durations)
sleep_ms(1000) # Pause between tunes
# Start NeoPixel animation
while True:
display_reducing_square()