2010.9.26-
自動演奏「ミニドラム・ミニ鉄琴」
小山智史(弘前大学)

 おもちゃのドラムやおもちゃの鉄琴をブラウザ制御で自動演奏します。

  1. WebIO.inoを書き込んだArduinoMicroPro(LeonardoでもOK)にモーターなどを接続して楽器を作ります。
  2. 上記ArduinoをパソコンにUSB接続します。
  3. 楽器を演奏するプログラムをWebページとして作り、webio.jsと共にサーバに置きます(ローカルファイルでも構いません)。
  4. 上記ページをブラウザで表示し、楽器を演奏します。ブラウザで音を出すこともできます。
  5. さまざまな楽器を接続した複数のパソコンで上記ページを表示すれば、同時に演奏できます。
  6. 「正時」に演奏させれば「からくり時計」になります。

 ものづくり教材として利用する場合は、グループでセッションが面白いのではないでしょうか(どなたか挑戦してみませんか?)。また、生徒の余力に応じて

  • 好きな曲の楽譜を入力する
  • キャラクターやデザインを工夫する
  • ドラムや鉄琴を手作りする
  • ドラムや鉄琴以外のユニークな楽器を考える
など、挑戦する箇所がたくさんあります。教師が工夫したものを生徒に作らせるだけでも、市販のキットを作るより遥かに面白いと思います(生徒も先生も)

(クリスマスバージョン)

□ オモチャのドラムの自動演奏

 オモチャのドラムを左右2つのスティックで叩きます。左のスティックはセンタードラム(L)とサイドドラム(S)、右のスティックはセンタードラム(R)とハイハット(H)を担当し、サーボモータでそれぞれのドラム位置にスティックを移動します。

drum1.html:

<!DOCTYPE html><html lang="ja"><head> <meta charset="utf-8"> <title>ドラムの自動演奏</title> <script src=webio.js></script> </head><body> <!-- ここからWebページの本体とプログラム --> <h2 align=center>ドラムの自動演奏</h2> <button onclick=playNotes()>演奏開始</button> <script> // ----------------------------------------------------------------------------- var notes=[ // 楽譜データ[音符, ドラム] [4,"L"],[8,"L"],[8,"R"],[4,"L"],[4,"R"], [4,""], [4,"S"], [4,"H"] ]; // ----------------------------------------------------------------------------- var TEMPO=120; // 1分間に4分音符を120回 var Td=100; // ドラムを打つ時間(100ms)...バチによって調整 var Ts=500; // サーボモーターの移動時間 var Lmotor=8, Rmotor=7, Lservo=10, Rservo=9; // モーターとサーボモーターのpin var Lstick={L:150, S:80}; // ドラムの左サーボの角度(個別に調整) var Rstick={R:0, H:60}; // ドラムの右サーボの角度(個別に調整) var p=-1; function setup(){ // --- はじめに自動実行 --- } function playNotes(){ var T, u; if(p<0) T=Ts; // 初回は準備 else{ // 1音目からは T=60000/TEMPO*4/notes[p][0]; // 4分音符 0.5秒, 8分音符 0.25秒 u=notes[p][1]; // L R S H if(u.match(/L/) || u.match(/S/)) digitalWrite(Lmotor, 1, Td); // 左を叩く if(u.match(/R/) || u.match(/H/)) digitalWrite(Rmotor, 1, Td); // 右を叩く } if(++p<notes.length){ // 次音の準備 u=notes[p][1]; if(u.match(/L/)) setTimeout("servo(Lservo,"+Lstick["L"]+",Ts)", T/2); else if(u.match(/S/)) setTimeout("servo(Lservo,"+Lstick["S"]+",Ts)", T/2); if(u.match(/R/)) setTimeout("servo(Rservo,"+Rstick["R"]+",Ts)", T/2); else if(u.match(/H/)) setTimeout("servo(Rservo,"+Rstick["H"]+",Ts)", T/2); setTimeout("playNotes()", T); }else p=-1; // 演奏終了 } </script> <!-- ここまで --> </body></html>

□ オモチャの鉄琴の自動演奏

 オモチャの鉄琴を左右2つのスティックで叩きます。左のスティックはドレミファ(C4 D4 E4 F4)、右のスティックはソラシド(G4 A4 B4 C5)を担当し、サーボモータでそれぞれの位置にスティックを移動します。

tekkin1.html:

<!DOCTYPE html><html lang="ja"><head> <meta charset="utf-8"> <title>鉄琴の自動演奏</title> <script src=webio.js></script> </head><body> <!-- ここからWebページの本体とプログラム --> <h2 align=center>鉄琴の自動演奏</h2> <button onclick=playNotes()>演奏開始</button> <script> // ----------------------------------------------------------------------------- var notes=[ // 楽譜データ[音符, Note] [4,"C5"], [8,"G4"],[8,"G4"],[4,"A4"],[4,"G4"], [4,""], [4,"B4"], [4,"C5"] ]; // ----------------------------------------------------------------------------- var TEMPO=120; // 1分間に4分音符を120回 var Td=80; // 鉄琴を打つ時間(80ms)...バチによって調整 var Ts=500; // サーボモーターの移動時間 var Lmotor=8, Rmotor=7, Lservo=10, Rservo=9; // モーターとサーボモーターのpin var Langle={C4:10, D4:35, E4:60, F4:80}; // 鉄琴の左サーボの角度(個別に調整) var Rangle={G4:75, A4:95, B4:120,C5:155} // 鉄琴の右サーボの角度(個別に調整) var p=-1; function setup(){ // --- はじめに自動実行 --- } function playNotes(){ var T, u; if(p<0) T=Ts; // 初回は準備 else{ // 1音目からは T=60000/TEMPO*4/notes[p][0]; // 4分音符 0.5秒, 8分音符 0.25秒 u=notes[p][1]; // C4 D4 ... A4 B4 C5 if(u in Langle) digitalWrite(Lmotor, 1, Td); // 左を叩く if(u in Rangle) digitalWrite(Rmotor, 1, Td); // 右を叩く } if(++p<notes.length){ // 次音の準備 u=notes[p][1]; if(u in Langle) setTimeout("servo(Lservo,"+Langle[u]+",Ts)", T/2); if(u in Rangle) setTimeout("servo(Rservo,"+Rangle[u]+",Ts)", T/2); setTimeout("playNotes()", T); }else p=-1; // 演奏終了 } </script> <!-- ここまで --> </body></html>

□ みんなでセッション

 複数の楽器で「セッション」も楽しめます。グループ学習でやってみると面白いと思います。ブラウザ画面から音が出ますので、楽器が1台でも十分楽しめます。

 それぞれのパソコンのブラウザ画面でを押すと、「正10秒」まで待って演奏を開始します。ボタンを押すタイミングが少しずれても大丈夫です。パソコンの時刻同期の設定をきちんとしておくと時刻のズレを少なくできます(NICTのページで確認できます)。ここではパソコン毎に多少時刻がずれていてもいいように、±1秒の範囲で調整できるようにしてあります。

session1.html:

<!DOCTYPE html><html lang="ja"><head> <meta charset="utf-8"> <title>みんなでセッション</title> <script src=webio.js></script> </head><body> <!-- ここからWebページの本体とプログラム --> <h2 align=center>みんなでセッション</h2> <button onclick=playNotes()>演奏開始</button> <script> // ----------------------------------------------------------------------------- var notes=[ // 楽譜データ[音符, Note, ドラム] [4,"C5","LH"], [8,"G4","SH"],[8,"G4","SH"], [4,"A4","LH"], [4,"G4","SH"], [4,"",""], [4,"B4","LR"], [4,"C5","SH"] ]; // ----------------------------------------------------------------------------- var TEMPO=120; // 1分間に4分音符を120回 var Td=80; // ドラムを打つ時間(100ms)...バチによって調整 var Ts=500; // サーボモーターの移動時間 var Lmotor=8, Rmotor=7, Lservo=10, Rservo=9; // モーターとサーボモーターのpin var Lstick={L:150, S:80}; // ドラムの左サーボの角度(個別に調整) var Rstick={R:0, H:60}; // ドラムの右サーボの角度(個別に調整) var Langle={C4:10, D4:35, E4:60, F4:80}; // 鉄琴の左サーボの角度(個別に調整) var Rangle={G4:75, A4:95, B4:120, C5:150} // 鉄琴の右サーボの角度(個別に調整) var p=-1; function setup(){ // --- はじめに自動実行 --- pinMode(5, INPUT_PULLUP); // 鉄琴はpin5をGNDに接続する } function playNotes(){ var T, u; if(p<0) T=Ts; // 初回は準備 else{ // 1音目からは u=notes[p][1]; // C3 D3 ... C4 T=60000/TEMPO*4/notes[p][0]; // 4分音符 0.5秒, 8分音符 0.25秒 if(u){ sendNote(midiPitch[u], T*.9); // スピーカから電子音 playNote(midiPitch[u], T*.9); // ブラウザから合成音 if(digitalRead(5)==0){ // 鉄琴(pin5をGNDに接続)ならば if(u in Langle) digitalWrite(Lmotor, 1, Td); // 左を叩く if(u in Rangle) digitalWrite(Rmotor, 1, Td); // 右を叩く } } u=notes[p][2]; // S(sidedrum) L R(centerdrum) H(hihat) if(u.match(/L/) || u.match(/R/)) drumKick(); // ブラウザからcenterdrum音 if(u.match(/S/)) drumSnare(); // ブラウザからsidedrum音 if(u.match(/H/)) drumHihat(); // ブラウザからhihat音 if(digitalRead(5)==1){ // ドラム(pin5を解放)ならば if(u.match(/L/) || u.match(/S/)) digitalWrite(Lmotor, 1, Td); // 左を叩く if(u.match(/R/) || u.match(/H/)) digitalWrite(Rmotor, 1, Td); // 右を叩く } } if(++p<notes.length){ // 次音の準備 if(digitalRead(5)==0){ // 鉄琴(pin5をGNDに接続)ならば u=notes[p][1]; if(u in Langle) setTimeout("servo(Lservo,"+Langle[u]+",Ts)",T/2); if(u in Rangle) setTimeout("servo(Rservo,"+Rangle[u]+",Ts)",T/2); }else{ // ドラム(pin5を解放)ならば u=notes[p][2]; if(u.match(/L/)) setTimeout("servo(Lservo,"+Lstick["L"]+",Ts)", T/2); else if(u.match(/S/)) setTimeout("servo(Lservo,"+Lstick["S"]+",Ts)", T/2); if(u.match(/R/)) setTimeout("servo(Rservo,"+Rstick["R"]+",Ts)", T/2); else if(u.match(/H/)) setTimeout("servo(Rservo,"+Rstick["H"]+",Ts)", T/2); } setTimeout("playNotes()", T); }else p=-1; // 演奏終了 } </script> <!-- ここまで --> </body></html>



 以下は楽譜データを分けて(sample.js, akahana.js, ...)、曲を選択できるようにした例です。NeoPixelをつなぐと演奏に連動してカラフルに光ります。イルミネーションのオブジェはngo-tecさんのページを見て作りました。「正10秒」で同期演奏できますし、「正時」に演奏させれば「からくり時計」となります。ブラウザ画面上で楽譜を入力して演奏させることもできます。

時刻合わせの方法(Windows10)
  1. NICTのページで時刻を確認する。「あなたのコンピュータの内蔵時計」が合っていれば以下の調整の必要はない。
  2. タスクバーの時刻表示を右クリックし、「日付と時刻の調整」を選ぶ。
  3. 「時刻を自動的に設定する」をオフにする。
  4. 「日付、時刻、地域の追加設定」で「日付と時刻」を選ぶと設定用ウィンドウが現れる。
  5. 「インターネット時刻」タブの「設定の変更」で「インターネット時刻サーバーと同期する」をチェックし、サーバーを「ntp.nict.jp」にして「今すぐ更新」ボタンを押す。
  6. 上記NICTのページを再読込みして時刻が合っていることを確認する。

(以下は2010年当時の内容です)

Arduino-tiny2313で自動演奏「ミニドラム・ミニ鉄琴」

 おもちゃのドラムやおもちゃの鉄琴をマイコン制御で演奏します。AVRマイコン(ATtiny2313)を使い、Arduino IDEで開発しました。

 ものづくり教材として利用する場合は、グループでバンド演奏させると面白いのではないでしょうか(どなたか挑戦してみませんか?)。また、生徒の余力に応じて

など、挑戦する箇所がたくさんあります。教師が工夫したものを生徒に作らせるだけでも、市販のキットを作るより遥かに面白いと思います(生徒も先生も)

 鉄琴(1400円)を別にして、製作費は約2500円(サーボモータを省略したドラムなら1000円以下)で済みます。ドラムは身の回りの廃品を利用して作ると楽しいでしょう。

 なお、ミニドラムの構想は野尻抱介氏のリズムボット(Make, vol.06, p37)を参考にしました。


□ ミニドラム

 レパートリーは「ジングルベル」「赤鼻のトナカイ」「大きなたいこ」「大きな古時計」「ハッピーバースデー」「クリスタルチルドレン」「附属特別支援学校校歌」...。

 右下の動画は電子オルゴールと組み合わせたものです。同期をとっていないので、音がちょっとずれています。

プログラム(スケッチ): drum.ino, drum1.h, drum2.h


□ ミニ鉄琴

 左のバチはドレミファソラ、右のバチはレミファソラシドを担当します。

 レパートリーは「ハッピーバースデー」...。

 右下の動画はドラムと組み合わせたものです。同期をとっていないので、音がちょっとずれています。

プログラム(スケッチ): tbirth.ino, tekkin1.h, tekkin2.h, (tekkin.ino...位置調整用)

 正味の楽譜データは

  1. 音を「,」で区切る。
  2. 音は、以下を「+」で組み合わせて表す。ただし、左右の位置を同時に移動はできない。
以下は tbirth.ino の例:


□ 製作メモ

回路図(ドラムと鉄琴で共通):

部品表:

主な部品
部品名・型番備考(参考価格 他)
AVRマイコン ATtiny2313V1秋月 @100
圧電スピーカ SPT08
(ミニ鉄琴では使わない)
1秋月 @50
サーボモータ GWS PICO/STD/F2秋月 @800×2
モータ (12V用手持ち品)2@100×2
ブレッドボード EIC-3011秋月 @150
ジャンパワイヤ 15cm赤白黒 各4本秋月
アルカリ電池(単3)3 
電池ボックス(単3×3)1秋月 @50
トグルスイッチ1 
トランジスタ 2SC21202秋月 @10×2
カーボン抵抗(1/4 W) 10Ω, 220Ω各2秋月
電解コンデンサ 1000μF 6.3V1秋月
太鼓1ダイソー @100
アンパンマン シロホン
(おもちゃの鉄琴)
1ピノチオ @1400


(イラスト 鎌田順子)
koyama@hirosaki-u.ac.jp