【メロディーメイカー】唱

# 概要

子ども向けのプログラミング教育プロジェクトとして、Adoの唱をコーディングしてみました。


<iframe width="400" height="712" src="https://www.youtube.com/embed/xzjaBPw3UG4" title="電子工作で唱part2" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

# ソースコード

```python:main.py
from melody_maker import *

def show():
    """
    唱
    """
    BPM = 132
    BEAT = 60 / BPM
    melody = [
        [Eb5, BEAT/2],[Eb6, BEAT/4],[REST, BEAT/4],[Eb6, BEAT/4],[REST, BEAT/4],[Eb6, BEAT/4],[REST, BEAT/4],[Eb6, BEAT/4],[REST, BEAT/4],[Bb5, BEAT/2],[Ab5, BEAT/2],
        [Bb5, BEAT],[Db6, BEAT*1.5/2],[Ab5, BEAT/4],[Ab5, BEAT/2],[Ab5, BEAT],[Ab5, BEAT/2],
        [Gb5 ,BEAT/2],[Ab5 ,BEAT/2],[Bb5 ,BEAT/2],[Db6 ,BEAT/2],[Eb6 ,BEAT/2],[Eb5 ,BEAT/2],[Eb5 ,BEAT/2],[Eb5 ,BEAT/2],
        [Eb5 ,BEAT/2],[Bb5 ,BEAT/2],[Bb5 ,BEAT/2],[Bb5 ,BEAT/4],[Bb5 ,BEAT/4],[Bb5 ,BEAT/2],[Db6 ,BEAT/2],[Db6 ,BEAT/2],[Eb6 ,BEAT/2],
        [Bb5, BEAT/2],[Ab5, BEAT/2],[Gb5, BEAT],[Bb5, BEAT/2],[Ab5, BEAT/2],[Gb5, BEAT],
        [Bb5, BEAT],[Db6, BEAT*1.5/2],[Ab5, BEAT/4],[Ab5, BEAT/2],[Ab5, BEAT],[Ab5, BEAT/2],
        [Gb5 ,BEAT/2],[Ab5 ,BEAT/2],[Bb5 ,BEAT/2],[Db6 ,BEAT/2],[Eb6 ,BEAT/2],[Eb5 ,BEAT/2],[Eb5 ,BEAT/2],[Eb5 ,BEAT/2],
        [Eb5 ,BEAT/2],[Bb5 ,BEAT/2],[Bb5 ,BEAT/2],[Bb5 ,BEAT/4],[Bb5 ,BEAT/4],[Bb5 ,BEAT/2],[Db6 ,BEAT/2],[Db6 ,BEAT/2],[Eb6 ,BEAT/2],
        [Bb5, BEAT/2],[Ab5, BEAT/2],[Gb5, BEAT],[Bb5, BEAT/2],[Ab5, BEAT/2],[Gb5, BEAT],[REST, BEAT]
    ]   
    for m in melody:
        tone(m[0], m[1])


while True:
    turn_on_led(color)
    if button_red.value() == 1:
        show()
    elif button_green.value() == 1:
        pass
    elif button_blue.value() == 1:
        pass
    elif button_yellow.value() == 1:
        pass
    elif button_orange.value() == 1:
        pass
    sleep(0.1)
    turn_off_led(color)
    if color < 4:
        color += 1
    else:
        color = 0

```

```python:melody_maker.py
from machine import Pin, PWM
from utime import sleep

# 演奏中かどうか
PLAY = False

# LED
led_red = Pin(0, Pin.OUT, value=1)
led_green = Pin(2, Pin.OUT, value=1)
led_blue = Pin(3, Pin.OUT, value=1)
led_yellow = Pin(9, Pin.OUT, value=1)
led_white = Pin(10, Pin.OUT, value=1)
led_red2 = Pin(1, Pin.OUT, value=1)
led_green2 = Pin(11, Pin.OUT, value=1)
led_blue2 = Pin(12, Pin.OUT, value=1)

# NPNトランジスタのベース
buzzer = PWM(Pin(15))

# 再生ボタン
button_yellow= Pin(13, Pin.IN, Pin.PULL_DOWN)
# 停止ボタン
button_orange = Pin(14, Pin.IN, Pin.PULL_DOWN)

def stop(pin):
    global PLAY
    PLAY = False
    print('STOP')

button_orange.irq(trigger=Pin.IRQ_RISING, handler=stop)


# 音の周波数
REST=    0
C4  =  262
Db4 =  277
D4  =  294
Eb4 =  311
E4  =  330
F4  =  349
Gb4 =  370
G4  =  392
Ab4 =  415
A4  =  440
Bb4 =  466
B4  =  494
C5  =  523
Db5 =  554
D5  =  587
Eb5 =  622 # 使っている
E5  =  659
F5  =  698
Gb5 =  740 # 使っている
G5  =  784
Ab5 =  831 # 使っている
A5  =  880
Bb5 =  932 # 使っている
B5  =  988
C6  = 1047
Db6 = 1109 # 使っている
D6  = 1175
Eb6 = 1245 # 使っている
E6  = 1319
F6  = 1397
Gb6 = 1480
G6  = 1568
Ab6 = 1661
A6  = 1760


# 光っているLEDを管理する変数
color = 0

def turn_on_led(color):
    """
    指定したLEDを点灯する。

    Parameters:
        color(int):
            0: 赤
            1: 緑
            2: 青
            3: 黄色
            4: 白
            5: 赤2
            6: 緑2
            7: 青2
    """
    if color == 0:
        led_red.value(0)
    elif color == 1:
        led_green.value(0)
    elif color == 2:
        led_blue.value(0)
    elif color == 3:
        led_yellow.value(0)
    elif color == 4:
        led_white.value(0)
    elif color == 5:
        led_red2.value(0)
    elif color == 6:
        led_green2.value(0)
    elif color == 7:
        led_blue2.value(0)
        
def turn_off_led(color):
    """
    指定したLEDを消灯する。
    
    Parameters:
        color(int):
            0: 赤
            1: 緑
            2: 青
            3: 黄色
            4: 白
            5: 赤2
            6: 緑2
            7: 青2
    """
    if color == 0:
        led_red.value(1)
    elif color == 1:
        led_green.value(1)
    elif color == 2:
        led_blue.value(1)
    elif color == 3:
        led_yellow.value(1)
    elif color == 4:
        led_white.value(1)
    elif color == 5:
        led_red2.value(1)
    elif color == 6:
        led_green2.value(1)
    elif color == 7:
        led_blue2.value(1)


def tone(frequency, duration):
    """
    パッシブブザーで音を鳴らす。

    Parameters:
        frequency(int): 周波数
        duration(float): 音の長さ
    """
    global color
    if frequency == REST:
        turn_on_led(0)
        turn_on_led(1)
        turn_on_led(2)
        turn_on_led(3)
        turn_on_led(4)
        turn_on_led(5)
        turn_on_led(6)
        turn_on_led(7)
        sleep(duration)
        turn_off_led(0)
        turn_off_led(1)
        turn_off_led(2)
        turn_off_led(3)
        turn_off_led(4)
        turn_off_led(5)
        turn_off_led(6)
        turn_off_led(7)
        return
    if frequency == Eb5:
        color = 0
    elif frequency == Eb6:
        color = 7
    elif frequency == Gb5:
        color = 1
    elif frequency == Ab5:
        color = 2
    elif frequency == Bb5:
        color = 4
    elif frequency == Db6:
        color = 6
    turn_on_led(color)
    buzzer.freq(frequency)
    buzzer.duty_u16(30000)
    sleep(duration)
    buzzer.duty_u16(0)
    sleep(0.002)
    turn_off_led(color)
    if color < 7:
        color += 1
    else:
        color = 0


```

# メロディーメイカーの作り方

動画で作り方を解説しています。

https://youtu.be/d7pTfG6R1M8