概要
子ども向けのプログラミング教育の一環として、電子工作とプログラムでメロディーを鳴らすプロジェクト(メロディーメイカー)を作成しました。
ドラマ「いちばんすきな花」の主題歌である藤井風の花をコーディングしてみました。
ソースコード
main.py
from machine import Pin, PWM
from utime import sleep
################ 電子回路に応じてピン番号を変更する ################
# LED
led_pins = [0, 2, 3, 9, 10, 1, 11, 12]
leds = [Pin(pin, Pin.OUT, value=1) for pin in led_pins]
# NPNトランジスタのベース
buzzer = PWM(Pin(15))
# 再生ボタン
play_button = Pin(13, Pin.IN, Pin.PULL_DOWN)
# 停止ボタン
stop_button = Pin(14, Pin.IN, Pin.PULL_DOWN)
######################## グローバル変数 #########################
# 演奏中ならTrue, 演奏していない時はFalse
PLAYING = False
# メロディー
MELODY = []
# スケール(メロディーの中で使っている音階)
SCALE = []
# BPM(1分あたりの拍数)
BPM = 0
################################################## 音階周波数 ##################################################
REST= 0
C3, Db3, D3, Eb3, E3, F3, Gb3, G3, Ab3, A3, Bb3, B3 = 131, 139, 147, 156, 165, 175, 185, 196, 208, 220, 233, 247
C4, Db4, D4, Eb4, E4, F4, Gb4, G4, Ab4, A4, Bb4, B4 = 262, 277, 294, 311, 330, 349, 370, 392, 415, 440, 466, 494
C5, Db5, D5, Eb5, E5, F5, Gb5, G5, Ab5, A5, Bb5, B5 = 523, 554, 587, 622, 659, 698, 740, 784, 831, 880, 932, 988
C6, Db6, D6, Eb6, E6, F6, Gb6, G6, Ab6, A6, Bb6, B6 =1047,1109,1175,1245,1319,1397,1480,1568,1661,1760,1865,1976
####################### 共通メソッド #######################
def turn_on_led(index=None):
"""
LEDを点灯する。
"""
if index is None:
for led in leds:
led.value(0)
else:
leds[index].value(0)
def turn_off_led(index=None):
"""
LEDを消灯する。
"""
if index is None:
for led in leds:
led.value(1)
else:
leds[index].value(1)
def tone(frequency, duration):
"""
音を鳴らす。
Parameters:
frequency(int): 周波数
duration(int): 音符の音の長さ
* 四分音符: 1/4
* 八分音符: 1/8
* 付点四分音符: 1.5/4
"""
beat = 60 / BPM
duration = beat * 4 * duration
if frequency == REST:
turn_on_led()
sleep(duration)
turn_off_led()
return
index = SCALE.index(frequency) % 8
turn_on_led(index)
buzzer.freq(frequency)
buzzer.duty_u16(30000)
sleep(duration)
buzzer.duty_u16(0)
sleep(0.002)
turn_off_led(index)
def play():
"""
演奏を開始する。
"""
global PLAYING
PLAYING = True
turn_off_led()
for m in MELODY:
if PLAYING:
tone(m[0], m[1])
else:
break
def stop(pin):
"""
演奏を停止する。
"""
global PLAYING
PLAYING = False
# 停止ボタンが押されたら演奏を停止する
stop_button.irq(trigger=Pin.IRQ_RISING, handler=stop)
def melody():
"""
Hana: Fujii Kaze
"""
global BPM
global MELODY
global SCALE
# BPMを定義する
BPM = 123
# メロディーを定義する
MELODY = [
(C5,1/8),(Bb4,1/8),(Ab4,1/8),(G4,1/8),
(F4,1/4),(Eb5,1/8),(F3,1/8),(D5,1/8),(Eb5,1/8),(F4,1/8),(Eb5,1/8),
(REST,1/8),(Bb3,1/8),(Eb5,1/8),(Bb3,1/8),(D5,1/8),(Eb5,1/8),(Bb4,1/8),(D5,1/8),
(REST,1/8),(Eb3,1/8),(D5,1/8),(Eb3,1/8),(C5,1/8),(D5,1/8),(Eb4,1/8),(D5,1/8),
(REST,1/8),(C3,1/8),(D5,1/8),(C3,1/8),(C5,1/8),(D5,1/8),(C4,1/8),(Eb5,1/8),
(REST,1/8),(F3,1/8),(Eb5,1/8),(F3,1/8),(D5,1/8),(Eb5,1/8),(F4,1/8),(Eb5,1/8),
(REST,1/8),(Bb3,1/8),(Eb5,1/8),(Bb3,1/8),(D5,1/8),(Eb5,1/8),(Bb4,1/8),(F5,1/8),
(REST,1/8),(Eb3,1/8),(F5,1/8),(Eb3,1/8),(Eb5,1/8),(F5,1/8),(Eb4,1/8),(F5,1/8),
(REST,1/8),(C3,1/8),(F5,1/8),(C3,1/8),(Eb5,1/8),(Eb5,1/8),(C4,1/8),(G5,1/8),
]
# スケールを更新する
unique_elements = []
for note in MELODY:
if note[0] not in unique_elements and note[0] != REST:
unique_elements.append(note[0])
SCALE = sorted(unique_elements)
# 演奏する
play()
index = 0
while True:
turn_on_led(index)
if play_button.value() == 1:
melody()
sleep(0.1)
turn_off_led(index)
if index < 7:
index += 1
else:
index = 0
メロディーメイカーの作り方
メロディーメイカーの作り方は以下の動画で解説しています。