旅する情報系大学院生

旅と留学とプログラミング

Raspberry piでステッピングモータを制御し、音楽を奏でる

この記事はTSGアドベントカレンダーの一部として書かれました。

www.adventar.org



まずは動画から。こんなものを作りました。
(音量小さいかも)

youtu.be

全体像f:id:yamaguchi_1024:20151204234635j:plain

ラズパイにsshし、ラズパイからステッピングモーターの周波数を電気パルスで与えることによって制御しています。
音の高さは周波数によって決まるため、周波数と回転の継続時間を調整することにより、音符(ソの四分音符とか)が表現できます。
パルスの増幅に使うステッピングモータードライバも自作しました。

制作の流れ

部品を買う

ラズパイのGPIO端子を使ってLチカできるくらいには設定する

ドライバを作ってステッピングモーターを動くようにする

曲の設定

という感じです。ドライバを作ってステッピングモーターが動くようにするのが一番大変でしたが、あとはpythonスクリプト書くだけなのでお手軽です。

部品を買う

実際に使用した部品は、

Raspberry Pi 2 Model B
ステッピングモーターST-42BYG020
ステッピングモータードライバキット(の一部)
ジャンパー線
9V電池
木箱

ですが、ステッピングモータードライバキットはそのままだと役立たずでかなり改造しないといけなかったので、普通にステッピングモータードライバ買ったほうがいいと思います。

ラズパイの設定

OSの入れ方とか初期設定の仕方が書かれたサイトはいくらでもあるので省略します。OSは普通にraspbianでいいと思います。
ちなみにLチカは以下のスクリプトでできます。

import RPi.GPIO as GPIO
import time

GPIO.setmode( GPIO.BOARD) 
GPIO.setup( 22, GPIO.OUT)

while True:
        GPIO.output( 22, GPIO.HIGH )
        time.sleep(0.2)
        GPIO.output( 22, GPIO.LOW )
        time.sleep(0.2)

このスクリプトの場合、22番端子(GPIO22じゃないよ!)にジャンパー線を繋いで適当な抵抗とLEDを直列に繋げばOKです。

ドライバを作る

素直にステッピングモータードライバを買うのがお手軽でいいと思いますが、トランジスタと抵抗と整流ダイオードとキャパシタがあればできたので、回路図を載せます。

f:id:yamaguchi_1024:20151204231410p:plain

初めて回路図を書いたので見づらいですね。ごめんなさい。
基本的にやってることはパルスの増幅だけなので回路自体は複雑ではないです。

曲の設定


以下がday dream cafeを演奏(?)するスクリプトです。

import RPi.GPIO as GPIO
import time

GPIO.setmode( GPIO.BOARD )
GPIO.setup( 22, GPIO.OUT )#25
GPIO.setup(13,GPIO.OUT)#27
GPIO.setup(16,GPIO.OUT)#23
GPIO.setup(18,GPIO.OUT)#24
#Time=0.004
do=1/523.251130
re=1/587.3295358
mi=1/659.25511
fa=1/698.456462
fas=1/739.9888454
so=1/783.990871
sos=1/830.6093951
ra=1/880.0
si=1/987.76660251
sif=1/932.327523
tdo=1/1046.502261

shi=15.0/27
hachi=15.0/54
ni=10.0/9

def onpu(onkai,nagasa):
  for i in range(0,int((nagasa/onkai)/5)):
    GPIO.output( 22, GPIO.HIGH )
    GPIO.output( 13, GPIO.HIGH )
    GPIO.output( 16, GPIO.LOW )
    GPIO.output( 18, GPIO.LOW )
    time.sleep(onkai)
    GPIO.output( 22, GPIO.LOW )
    GPIO.output( 13, GPIO.HIGH )
    GPIO.output( 16, GPIO.HIGH )
    GPIO.output( 18, GPIO.LOW )
    time.sleep(onkai)
    GPIO.output( 22, GPIO.LOW )
    GPIO.output( 13, GPIO.LOW )
    GPIO.output( 16, GPIO.HIGH )
    GPIO.output( 18, GPIO.HIGH )
    time.sleep(onkai)
    GPIO.output( 22, GPIO.HIGH )
    GPIO.output( 13, GPIO.LOW )
    GPIO.output( 16, GPIO.LOW )
    GPIO.output( 18, GPIO.HIGH )
    time.sleep(onkai)

  time.sleep(0.001)
 
def onpu2(onkai,nagasa):
  for i in range(0,int((nagasa/onkai)/5)):
    GPIO.output( 22, GPIO.HIGH )
    GPIO.output( 13, GPIO.HIGH )
    GPIO.output( 16, GPIO.LOW )
    GPIO.output( 18, GPIO.LOW )
    time.sleep(onkai)
    GPIO.output( 22, GPIO.LOW )
    GPIO.output( 13, GPIO.HIGH )
    GPIO.output( 16, GPIO.HIGH )
    GPIO.output( 18, GPIO.LOW )
    time.sleep(onkai)
    GPIO.output( 22, GPIO.LOW )
    GPIO.output( 13, GPIO.LOW )
    GPIO.output( 16, GPIO.HIGH )
    GPIO.output( 18, GPIO.HIGH )
    time.sleep(onkai)
    GPIO.output( 22, GPIO.HIGH )
    GPIO.output( 13, GPIO.LOW )
    GPIO.output( 16, GPIO.LOW )
    GPIO.output( 18, GPIO.HIGH )
    time.sleep(onkai)

def kyuhu(onkai,nagasa):
  for i in range(0,int((nagasa/onkai)/4)):
    time.sleep(onkai)
    time.sleep(onkai)
    time.sleep(onkai)
    time.sleep(onkai)

while True:
  onpu(mi,hachi)
  onpu(fa,hachi)
  onpu(so,hachi)
  onpu(ra,shi)
  onpu(ra,shi)
  onpu(ra,hachi)
  onpu(ra,shi)
  onpu(so,shi)
  onpu(so,hachi)
  onpu(fa,hachi)
  onpu(mi,hachi)
  onpu(fa,hachi)
  onpu(mi,hachi)
  onpu(re,hachi)
  onpu(do,shi)
  onpu(so,shi)
  onpu2(do,shi)
  onpu(do,hachi)
  onpu(so,shi)
  onpu(ra,hachi)
  onpu(so,hachi)
  onpu(fa,hachi)
  onpu(mi,ni)
  onpu(fa,shi)
  onpu(fa,shi)
  onpu(fa,hachi)
  onpu(fa,shi)
  onpu(mi,shi)
  onpu(mi,hachi)
  onpu(sos,hachi)
  onpu2(ra,shi)
  onpu(ra,hachi)
  onpu(re,hachi)
  onpu(mi,hachi)
  onpu(fa,hachi)
  onpu(mi,hachi)
  onpu(do,hachi)
  onpu(fa,hachi)
  onpu(mi,hachi)
  onpu(do,hachi)
  onpu(ra,hachi)
  onpu(so,ni)
  onpu(so,shi)
  onpu(so,hachi)
  onpu(ra,hachi)
  onpu(so,ni)

  time.sleep(2)


python全然書けないのでセンスのかけらもないスクリプトです。


結果

音楽はちゃんと聞こえますが、音が小さいです。