IBM Developer Day 2018에서 배포한 IoT 뱃지는 ESP32 Devkit을 기반으로 구성되어 있습니다. 배포 당시 설치된 행사용 소프트웨어 대신 마이크로 파이썬이 포팅된 펌웨어를 설치하면 IoT 뱃지를 개발 보드로 활용할 수 있습니다. 이 튜토리얼에서는 IoT Badge에 피에조 부저를 연결하고 마이크로 파이썬에서 PWM(Pulse Width Modulation)으로 간단한 음악을 연주하는 방법에 대해 학습합니다.

학습 목표

이 튜토리얼을 마치게 되면 다음과 같은 것을 할 수 있습니다:

  • REPL을 이용하여 IoT Badge에 마이크로 파이썬 코드 실행
  • 마이크로 파이썬 코드로 GPIO 포트로 PWM 출력

사전 준비 사항

  1. Developer Day 2018 IoT Badge 펌웨어 설치하기
  2. Developer Day 2018 IoT Badge에 나만의 파이썬 코드 실행하기
  3. IBM Developer Day 2018 IoT Badge
  4. 데이터 통신용 USB 2.0 Micro B Type 케이블 (마이크로 5핀)
  5. J8번 6핀 2.54mm Female 소켓 헤더 연결
  6. 피에조 부저

소요 시간

이 튜토리얼을 완료하기까지 대략 15분 정도가 소요됩니다.

단계

피에조부저 연결하기

피에조 부저는 다양하게 있으나 Developer Day 2018 행사를 통해 제공한 부저는 6.5mm 정도라 2.54mm 간격의 소켓에 딱맞는 않습니다. 그래서 4핀 소켓에 연결될 수 있도록 약간 다리 간격을 넓혀서 J8번 소켓에 꽂습니다.

J8번의 제일 왼쪽부터 첫 번째는 GPIO27번이고, 네 번째는 GND입니다. 부저의 + 기호쪽을 GPIO27번, – 기호쪽을 GND에 맞춰서 끼워넣습니다.

딱 맞지는 않지만 빠지지 않을 정도의 안정감이 있습니다. 연결이 완료되면 아래와 같은 모양이 됩니다.

마이크로 파이썬 코드 작성하기

피에조 부저는 PWM 방식으로 소리를 낼 수 있습니다. 마이크로 파이썬에서는 machine.PWM 모듈을 이용하여 GPIO 포트에 PWM 제어 기능을 제공하고 있습니다.

기본적으로 ESP32가 PWM이라는 것을 제공하는 것은 아니고 Timer를 이용하여 PWM을 구현한 모듈이므로 기본적으로 Timer 사용에 대한 제한이 있습니다.

기본 주파수가 1Hz부터 40MHz까지 설정 할 수 있지만 주파수값이 높아짐에 따라 duty 해상도는 감소되는 현상이 있습니다. 예를 들어 40MHz인 경우 해상도는 1bit가 되며 duty는 무조건 50%로 고정됩니다. 이와 관련한 자세한 설명은 ESP IDF-Supported Range of Frequency and Duty Resolution문서를 참고 하시기 바랍니다.

우선은 필요한 파이썬 모듈을 로딩합니다.

from machine import Pin
from machine import PWM
import time

그리고 J8의 GPIO27번 핀을 초기화하고 Pin에 대한 객체를 얻습니다.

p = Pin(27, Pin.OUT)

이제 machine.PWM 모듈에 27번 Pin에 대한 객체를 넘겨 PWM 객체를 생성하고 duty 값을 0으로 초기화 합니다.

pwm = PWM(p)
pwm.duty(0)

그리고, A4 (라)음계인 440Hz 주파수를 설정 후 duty 값을 50%로 설정합니다.

pwm.freq(440)
pwm.duty(50)

음에 대핸 소리를 들을 수 있습니다. 그렇다면, 바로 윗음인 B4(시) 494 그리고, C5(도) 523를 입력합니다.

pwm.freq(494)
pwm.freq(523)

그런데 PWM은 일정한 주파수를 지속적으로 내보내기 때문에 같은 소리가 계속 나게 됩니다. 그렇다면 특정한 소리를 특정한 시간동안 내려면 duty 값이 0%인 상태에서 소리를 내고자 할 때 50%로 설정하고 또 소리를 끄려면 다시 0%으로 설정하게 하부저면 됩니다. 그럼 이를 바탕으로 beeper라는 함수를 아래와 같이 만들어 볼 수 있습니다. 전달 인자 값이 없는 경우 기본값으로 C5음을 1초 동안 발생합니다.

def beeper(freq=523, duration=1000):
    pwm.freq(freq)
    pwm.duty(50)
    time.sleep_ms(duration)
    pwm.duty(0)

마이크로 파이썬으로 Tone Play 해보기

마이크로 파이썬 위키에는 pyboard의 Timer로 Tone Play를 하는 예제가 있습니다. 이 예제에는 각 음표에 대응하는 변수에 주파수를 미리 입력하고, 이 음표를 배열에 넣고 순서대로 재생하여 간단한 Tone Play를 합니다.

이를 IoT Badge용으로 포팅하면 다음과 같습니다.

from machine import Pin
from machine import PWM
import time

# define frequency for each tone
B0  = 31
C1  = 33
CS1 = 35
D1  = 37
DS1 = 39
E1  = 41
F1  = 44
FS1 = 46
G1  = 49
GS1 = 52
A1  = 55
AS1 = 58
B1  = 62
C2  = 65
CS2 = 69
D2  = 73
DS2 = 78
E2  = 82
F2  = 87
FS2 = 93
G2  = 98
GS2 = 104
A2  = 110
AS2 = 117
B2  = 123
C3  = 131
CS3 = 139
D3  = 147
DS3 = 156
E3  = 165
F3  = 175
FS3 = 185
G3  = 196
GS3 = 208
A3  = 220
AS3 = 233
B3  = 247
C4  = 262
CS4 = 277
D4  = 294
DS4 = 311
E4  = 330
F4  = 349
FS4 = 370
G4  = 392
GS4 = 415
A4  = 440
AS4 = 466
B4  = 494
C5  = 523
CS5 = 554
D5  = 587
DS5 = 622
E5  = 659
F5  = 698
FS5 = 740
G5  = 784
GS5 = 831
A5  = 880
AS5 = 932
B5  = 988
C6  = 1047
CS6 = 1109
D6  = 1175
DS6 = 1245
E6  = 1319
F6  = 1397
FS6 = 1480
G6  = 1568
GS6 = 1661
A6  = 1760
AS6 = 1865
B6  = 1976
C7  = 2093
CS7 = 2217
D7  = 2349
DS7 = 2489
E7  = 2637
F7  = 2794
FS7 = 2960
G7  = 3136
GS7 = 3322
A7  = 3520
AS7 = 3729
B7  = 3951
C8  = 4186
CS8 = 4435
D8  = 4699
DS8 = 4978

# set up pin PWM timer for output to buzzer or speaker
p = Pin(27, Pin.OUT)
pwm = PWM(p)
pwm.duty(0)

# play all tone
note = [B0, C1, CS1, D1, DS1, E1, F1, FS1, G1, GS1, A1, AS1, B1, C2, CS2, D2, DS2, E2, F2, FS2, G2, GS2, A2, AS2, B2, C3, CS3, D3, DS3, E3, F3, FS3, G3, GS3, A3, AS3, B3, C4, CS4, D4, DS4, E4, F4, FS4, G4, GS4, A4, AS4, B4, C5, CS5, D5, DS5, E5, F5, FS5, G5, GS5, A5, AS5, B5, C6, CS6, D6, DS6, E6, F6, FS6, G6, GS6, A6, AS6, B6, C7, CS7, D7, DS7, E7, F7, FS7, G7, GS7, A7, AS7, B7, C8, CS8, D8, DS8]

for i in note:
    pwm.freq(i)
    print(i)
    pwm.duty(30)
    time.sleep_ms(300)

mario = [E7, E7, 0, E7, 0, C7, E7, 0, G7, 0, 0, 0, G6, 0, 0, 0, C7, 0, 0, G6, 0, 0, E6, 0, 0, A6, 0, B6, 0, AS6, A6, 0, G6, E7, 0, G7, A7, 0, F7, G7, 0, E7, 0,C7, D7, B6, 0, 0, C7, 0, 0, G6, 0, 0, E6, 0, 0, A6, 0, B6, 0, AS6, A6, 0, G6, E7, 0, G7, A7, 0, F7, G7, 0, E7, 0,C7, D7, B6, 0, 0]

# play Mario Bros tone example
# source from here http://www.linuxcircle.com/2013/03/31/playing-mario-bros-tune-with-arduino-and-piezo-buzzer/
for i in mario:
    if i == 0:
        pwm.duty(0)
    else:
        pwm.freq(i) # change frequency for change tone
        pwm.duty(30)

    time.sleep_ms(150)

pwm.deinit()

맺음말

이 튜토리얼에서는 Develper Day 2018 IoT 뱃지와 피에조 부저를 이용하여 어떻게 마이크로 파이썬으로 PWM 제어를 하는지에 대해 알아보았습니다.