import machine
import time
buzzer = machine.PWM(machine.Pin(14))
# ── Note frequencies (Hz) ──────────────────────────
NOTES = {
'B3': 247,
'C4': 262, 'D4': 294, 'E4': 330, 'F4': 349,
'G4': 392, 'A4': 440, 'B4': 494,
'C5': 523, 'D5': 587, 'E5': 659, 'F5': 698,
'G5': 784, 'A5': 880,
'R': 0 # rest
}
# ── Timing — 140 BPM ───────────────────────────────
BPM = 140
Q = int(60000 / BPM) # quarter note ≈ 428 ms
E = Q // 2 # eighth ≈ 214 ms
S = Q // 4 # sixteenth ≈ 107 ms
H = Q * 2 # half ≈ 857 ms
DQ = Q + E # dotted quarter
GAP = 25 # articulation gap between notes
def play(note, dur):
if NOTES[note] == 0:
buzzer.duty_u16(0)
time.sleep_ms(dur)
else:
buzzer.freq(NOTES[note])
buzzer.duty_u16(32768) # 50% duty = max volume
time.sleep_ms(dur - GAP)
buzzer.duty_u16(0)
time.sleep_ms(GAP)
def play_song(melody):
for note, dur in melody:
play(note, dur)
# ── Monkey Dance melody ────────────────────────────
# Bouncy, syncopated, playful — 4/4 time
intro = [
('G4', E), ('G4', S), ('A4', S), ('G4', E), ('E4', E),
('D4', Q), ('R', E), ('D4', E),
('G4', E), ('G4', S), ('A4', S), ('G4', E), ('E4', E),
('C4', H),
]
verse = [
('E4', E), ('G4', E), ('A4', E), ('G4', E),
('E4', E), ('D4', E), ('E4', Q),
('G4', E), ('A4', E), ('B4', E), ('A4', E),
('G4', H),
('A4', E), ('A4', S), ('B4', S), ('A4', E), ('G4', E),
('E4', DQ), ('D4', S), ('E4', S),
('G4', E), ('G4', E), ('A4', E), ('G4', E),
('E4', H),
]
bridge = [
('C5', E), ('D5', E), ('E5', E), ('D5', E),
('C5', E), ('B4', E), ('A4', Q),
('B4', E), ('C5', E), ('D5', E), ('C5', E),
('B4', H),
('G4', S), ('A4', S), ('B4', E), ('C5', E), ('B4', E),
('A4', E), ('G4', E), ('A4', Q),
('G4', E), ('E4', E), ('G4', E), ('A4', E),
('G4', H),
]
# fast bouncy fill at the end
outro = [
('G4', S), ('A4', S), ('G4', S), ('E4', S),
('G4', S), ('A4', S), ('G4', S), ('E4', S),
('C5', E), ('B4', E), ('A4', E), ('G4', E),
('G4', H), ('R', Q),
]
# ── Run it ─────────────────────────────────────────
print("Monkey Dance!")
play_song(intro)
play_song(verse)
play_song(bridge)
play_song(verse) # repeat verse
play_song(outro)
buzzer.duty_u16(0)
buzzer.deinit()
print("Done!")