それでは、Arduinoの統合開発環境「Arduino IDE」で、スケッチ(プログラム)を作成していきましょう(スケッチ1)。
#include "pitches.h" //----------------------- // 定数の定義 //----------------------- const int BZ = 2; //ブザー(TMP36)の出力ピン const int nos = 5; //スイッチの数 const int SW[nos] = {3,4,5,6,7}; //各スイッチの入力ピン番号 //const int BOM = 10; //電磁石ピンの出力ピン(オプション) //スイッチの回路は負論理なので、ONがLOWになる const int SW_ON = LOW; const int SW_OFF = HIGH; //----------------------- // グローバル変数の定義 //----------------------- int G_old_val[nos] = {SW_OFF, SW_OFF, SW_OFF, SW_OFF, SW_OFF}; //前回のスイッチの値 int G_sw_val; void setup() { pinMode(BZ, OUTPUT); //ブザーを出力モードに設定 //スイッチを全て入力モードに設定 for(int i = 0; i < nos; i++){ pinMode(SW[i], INPUT); } // pinMode(BOM, OUTPUT); //電磁石ピンを出力モードに設定(オプション) randomSeed(analogRead(A0)); //乱数の初期設定に未接続ピンのノイズを利用 // digitalWrite(BOM, HIGH); //電磁石の電流を流す(オプション) bz_start(); //ゲームスタート音楽 } void loop() { int int_swNumber = -1; //何も押してないときの番号を設定 int int_rand = random(nos); //ランダムでハズレスイッチ番号を決定する //スイッチ1〜5の状態を取得 for(int i = 0; i < nos; i++){ G_sw_val = digitalRead(SW[i]); //スイッチの状態を読み取る if(G_sw_val == SW_ON && G_old_val[i] == SW_OFF){ int_swNumber = i; //スイッチの番号を取得 } G_old_val[i] = G_sw_val; //スイッチの値を保存 } //スイッチの入力があったとき if(int_swNumber != -1){ //ハズレスイッチ番号が押されたら、ゲーム終了 if(int_rand == int_swNumber){ bz_ending(); //エンディング音楽 // digitalWrite(BOM, LOW); //電磁石の電流をカット } //クリア音を流す else{ bz_levelup(); } } }
1行目の#includeで、「pitches.h」を読み込んでいます。これは、音階を宣言したファイルで、Arduinoのサンプルスケッチ「toneMelody」に入っています。この音階を使用して、ゲーム用のメロディーを作りました。
31行目のrandomSeed()は、乱数を発生するための初期処理です。使用していないアナログ入力ピン(A0)のノイズを引数にすることで、random()使用時に毎回違う値を取得できるようになります。
36行目から始まるloop()の中で、ゲームの判定を行います。int_swNumber変数にスイッチが押されていないときの番号「−1」をセットした後(37行目)、ランダム関数でハズレスイッチ番号を選んでいます(38行目)。
41〜47行目は、スイッチ1〜5までの入力値を見て、スイッチの状態をチェックしています。スイッチが押されていた場合は、int_swNumberにスイッチ番号を取得します(44行目)。
スイッチが押されていたときは、50〜59行目が実行され、アタリ/ハズレの判定を行い、それぞれに該当するメロディーを呼び出します。
今回、toneMelody()とゲームスタートを含む3曲分の楽譜を、ユーザー関数として作成しました。Arudino IDEには、音を鳴らすためのtone()が用意されています。tone()は引数に、出力するピン番号、周波数を指定して、メロディーを奏でることができます。
toneMelody()と、ゲームスタートのbz_start()でメロディーの作り方を見てみましょう(スケッチ2)。
//----------------------------------- // 指定した音階と長さでブザーを鳴らす // note:音階 duration:長さ //----------------------------------- void toneMelody(int note, int duration){ int noteDuration = 1000 / duration; //音の長さを決める tone(BZ, note); //ブザーを指定周波数 delay(noteDuration); //指定時間 鳴らす //音の切れ目を作る noteDuration = noteDuration * 0.1; //長さを決めている noTone(BZ); //ブザーへの出力を止める delay(noteDuration); //指定時間保つ } //----------------------- // スタート //----------------------- void bz_start(){ int melody[] = {NOTE_G5, NOTE_G5, 0, NOTE_G5, NOTE_F5, NOTE_G5, NOTE_AS5}; int noteDurations[] = {8,8,8,4,8,4,4}; for (int i = 0; i < 7; i++) { toneMelody(melody[i], noteDurations[i]); }
toneMelody()は、引数に音階と音の長さを指定して呼び出します。実際に鳴らす音の長さは計算で求めます。durationが「8」の場合は、1000÷8=125、つまり125ミリ秒間だけ音が鳴ります(5行目)。
tone()の引数に、出力するピン、周波数を指定し、delay()で出力する時間を指定しています(7〜8行目)。音と音が連続すると曲が歯切れよく聞こえないので、noTone()で音を止めます(12〜13行目)。
bz_start()には、音階と長さを記録してあります。要するに、これが楽譜です。20行目のmelody配列の要素は、「pitches.h」に宣言されている音階です。「pitches.h」には、B0〜DS8まで8オクターブの音(周波数)が定義されています。noteDurations配列には、melodyに入れた音の長さを要素として宣言します。
for文で配列の要素をループして、toneMelody()を呼び出せばブザーが鳴ります。
レベルアップとエンディングの音階は、ファイルに入っているのでダウンロードして確認してください。
Copyright © ITmedia, Inc. All Rights Reserved.