今回はアラーム音をメロディに変更します。
アラーム音をメロディに変えよう
ここまでのプログラミングで、キッチンタイマーとしての動作はある程度完成しました。
ただ、せっかく音楽まで鳴らせるスピーカーがあるのに、時間がきたら単調なアラーム音が鳴るだけではちょっと寂しいですよね。
そこで、今の単調なアラーム音をメロディーに変更しようと思います。
音階を#define定義する
第31回の記事で説明したように、Arduinoではtone()/noTone()命令で指定した周波数の音程を鳴らすことができます。
tone命令でいちいち数字を書いて周波数を指定するのはわかりづらいので、まずは音階の名前と周波数を#defineで定義しておきましょう。
#defineで音階名を定義する場合、日本人が慣れている「ドレミファソラシ」で名前を定義しようと思います。「ドレミファソラシ」はイタリア語表記です。日本語表記は「ハニホヘトイロ」になります。また英語表記では「CDEFGAB」になります。
考えてみると日本ではいろいろな表記が混在して使われていますよね。音程は普通「ドレミファ」を使いますが、曲調を表現する場合は「ハ長調」など「ハニホヘト」の日本語表記を使っています。またMacintoshでは無償の音楽作成アプリGarageBandが有名ですが、このようなDTMアプリ(音楽作成アプリ)では音階の指定に「CDEFG」が使われています。
音階はオクターブごとに番号が振られていて、普通のドは第4オクターブになっています。1オクターブ低いドは第3オクターブ、1オクターブ高いドは第5オクターブです。
またピアノの黒い鍵盤は隣の音と半音違いになり、左隣の音階名に「#」(シャープ)をつけます。
以上をまとめると以下のように音階名が決められています。
ということで、音階と周波数の定義は、音階名とオクターブ番号を使って#define定義しようと思います。例えば普通のド(第4オクターブのド)は262Hzですので以下のように定義しようと思います。
#define DO_4 262 // ド(第4オクターブ)
第4オクターブを中心に、3オクターブ分あればある程度の曲は作れると思いますので、以下のように3オクターブ分定義してみました。なお、半音の「#」など、記号はC/C++言語では特殊文字として扱われることがあるので、実際の#defineでは音階名に「S」(Sharpの頭文字)をつけて使うことにします。
// 音の周波数
#define DO_3 131
#define DOS_3 139
#define RE_3 147
#define RES_3 156
#define MI_3 165
#define FA_3 175
#define FAS_3 185
#define SO_3 196
#define SOS_3 208
#define RA_3 220
#define RAS_3 233
#define SI_3 247
#define DO_4 262
#define DOS_4 277
#define RE_4 294
#define RES_4 311
#define MI_4 330
#define FA_4 349
#define FAS_4 370
#define SO_4 392
#define SOS_4 415
#define RA_4 440
#define RAS_4 466
#define SI_4 494
#define DO_5 523
#define DOS_5 554
#define RE_5 587
#define RES_5 622
#define MI_5 659
#define FA_5 698
#define FAS_5 740
#define SO_5 784
#define SOS_5 831
#define RA_5 880
#define RAS_5 932
#define SI_5 988
音の鳴らし方
音階の#define定義はできましたので、この定義名を使って音を鳴らすことにします。tone命令で音を鳴らすことができますので、例えば普通のドを鳴らしたい場合は、
tone(SPEAKER, DO_4);
で鳴らすことができます。SPEAKERはスピーカーが接続されているArduioボードの端子番号で、#defineで定義しています。
違う音を鳴らしたい場合は、noTone()命令で音を止めなくても、先ほどの普通のドがなっている状態の時に
tone(SPEAKER, RE_4);
と書けばレの音を鳴らすことができます。
また音を止めるときはnoTone()命令を書けばOKです。
ということで適当なメロディーを作ってアラーム音をメロディー音に変更してみましょう。
メロディー音を作る
メロディーは最近の曲を使うと著作権の問題が出てきますので、適当にメロディーを作ってみました。それぞれの音の長さは200ms(ミリ秒)で、以下のメロディーにしてみます。何か好きな曲があればその曲にしてみてください。
「ドミソミドミソミドミソシド」
なんとも芸がないメロディーですが、スケッチはこのメロディーで行きましょう。
それぞれの音は200msの長さで鳴らしますので、以下のようにスケッチに書けばOKです。
// ド
tone(SPEAKER, DO_4);
delay(200);
// ミ
tone(SPEAKER, MI_4);
delay(200);
// ソ
tone(SPEAKER, SO_4);
delay(200);
// ミ
tone(SPEAKER, MI_4);
delay(200);
// ド
tone(SPEAKER, DO_4);
delay(200);
// ミ
tone(SPEAKER, MI_4);
delay(200);
// ソ
tone(SPEAKER, SO_4);
delay(200);
// ミ
tone(SPEAKER, MI_4);
delay(200);
// ド
tone(SPEAKER, DO_4);
delay(200);
// ミ
tone(SPEAKER, MI_4);
delay(200);
// ソ
tone(SPEAKER, SO_4);
delay(200);
// シ
tone(SPEAKER, SI_4);
delay(200);
// 1オクターブ高いド
tone(SPEAKER, DO_5);
delay(200);
// 音を消す
noTone(SPEAKER);
キッチンタイマーの時間が来たら、このメロディーを3回鳴らすようにしたいと思います。3回鳴らすのは簡単ですよね。今のスケッチがアラーム音を3回鳴らすようにしてありますので、その部分をメロディーに置き換えればOKです。
スケッチを作る
それではスケッチをメロディーを鳴らすように変更してみましょう。
スケッチのsetup()部分の前に音階の定義を書きます。また、アラーム音の部分をメロディーに置き換えればOKです。このように変更したスケッチを以下に示します。今回のスケッチの変更は入力すると面倒ですので、コピペしてしまいましょう。スケッチができたらArduino Microにスケッチを送って動作を確認してみましょう。
/*
* キッチンタイマー
*
* 内容: スイッチ、LED、スピーカーを使ったキッチンタイマー
* 変更履歴:
* 2019. 8.11: 新規作成
* 2019. 8.15: スタートスイッチ処理を追加
* 2019. 8.17: スイッチ関連の#define追加
* 2019. 9. 8: 点滅回数カウント追加
* 最終的に繰り返し処理をfor文で作成
* 2019. 9.16: スケッチ動作開始時にLEDを点滅
* 2019.10. 5: アラーム音追加
* 動作開始時とタイマー時間の時に青色LEDを点灯するように変更
* 2019.10.13: 残り時間LED制御追加
* 2019.10.14: 残り時間が5秒以下になったらスピーカーを鳴らす動作を追加
* 2019.11. 4: アラーム音をメロディーに変更
*/
// 秒を表現するLED関連(青色LED)
#define BYOU_LED 12 // 秒を表現する青色LEDの端子番号
#define BYOU_ON 50 // 秒を表現するLEDをつけている時間 (単位:ミリ秒)
#define BYOU_OFF 1000 - BYOU_ON // 秒を表現するLEDを消している時間 (単位:ミリ秒)
// 残り時間を表現するLED関連(緑色、黄色、赤色LED)
#define LED_MIDORI 8 // 緑色LEDの端子番号
#define LED_KIIRO 6 // 黄色LEDの端子番号
#define LED_AKA 4 // 赤色LEDの端子番号
// スタートスイッチ関連
#define SWITCH 23 // スイッチを接続している端子番号
#define SWITCH_OFF 1 // スイッチOFFの時のdigitalReadの値
#define SWITCH_ON 0 // スイッチONの時のdigitalReadの値
// タイマー時間設定(単位:秒)
#define TIMER_JIKAN 10
// 残り時間を表現するLEDの制御時間
#define KIIRO_JIKAN TIMER_JIKAN / 3
#define AKA_JIKAN TIMER_JIKAN / 3 * 2
// アラーム音関連
#define SPEAKER 18 // スピーカーの端子番号
#define ALARM 880 // 通常のアラーム音周波数
// 音の周波数
#define DO_3 131
#define DOS_3 139
#define RE_3 147
#define RES_3 156
#define MI_3 165
#define FA_3 175
#define FAS_3 185
#define SO_3 196
#define SOS_3 208
#define RA_3 220
#define RAS_3 233
#define SI_3 247
#define DO_4 262
#define DOS_4 277
#define RE_4 294
#define RES_4 311
#define MI_4 330
#define FA_4 349
#define FAS_4 370
#define SO_4 392
#define SOS_4 415
#define RA_4 440
#define RAS_4 466
#define SI_4 494
#define DO_5 523
#define DOS_5 554
#define RE_5 587
#define RES_5 622
#define MI_5 659
#define FA_5 698
#define FAS_5 740
#define SO_5 784
#define SOS_5 831
#define RA_5 880
#define RAS_5 932
#define SI_5 988
void setup() {
// 端子の設定
pinMode(BYOU_LED, OUTPUT); // 青色LED接続端子設定
pinMode(LED_MIDORI, OUTPUT); // 緑色LED接続端子設定
pinMode(LED_KIIRO, OUTPUT); // 緑色LED接続端子設定
pinMode(LED_AKA, OUTPUT); // 緑色LED接続端子設定
pinMode(SWITCH, INPUT_PULLUP); // スイッチ接続端子の設定
// 秒のLED(青色LED)を点灯する
digitalWrite(BYOU_LED, HIGH);
// スイッチが押されるまで待つ
while(digitalRead(SWITCH) == SWITCH_OFF) {
}
// タイマー開始時に緑色LEDを点灯
digitalWrite(LED_MIDORI, HIGH);
}
void loop() {
// for文で回数を数えるために使用する変数
uint8_t count;
// TIMER_JIKAN分の回数を数える
for( count=0; count<TIMER_JIKAN; count++) {
// 残り時間表現用LEDの制御
if( count == KIIRO_JIKAN ) {
digitalWrite(LED_MIDORI, LOW);
digitalWrite(LED_KIIRO, HIGH);
}
if( count == AKA_JIKAN ){
digitalWrite(LED_KIIRO, LOW);
digitalWrite(LED_AKA, HIGH);
}
// 残り時間に応じて処理を変える
if( (TIMER_JIKAN-count) <= 5 ) {
// 残り時間が5秒以下になったら、1秒に1回青色LEDを点滅して音を鳴らす
digitalWrite(BYOU_LED, HIGH);
tone(SPEAKER, ALARM);
delay(BYOU_ON);
digitalWrite(BYOU_LED, LOW);
noTone(SPEAKER);
delay(BYOU_OFF);
} else {
// そうでなければ、1秒に1回青色LEDを点滅する
digitalWrite(BYOU_LED, HIGH);
delay(BYOU_ON);
digitalWrite(BYOU_LED, LOW);
delay(BYOU_OFF);
}
}
// 時間になったので秒のLED(青色LED)を点灯する
digitalWrite(BYOU_LED, HIGH);
// メロディー音を3回鳴らす
for( count=0; count<3; count++) {
// ド
tone(SPEAKER, DO_4);
delay(200);
// ミ
tone(SPEAKER, MI_4);
delay(200);
// ソ
tone(SPEAKER, SO_4);
delay(200);
// ミ
tone(SPEAKER, MI_4);
delay(200);
// ド
tone(SPEAKER, DO_4);
delay(200);
// ミ
tone(SPEAKER, MI_4);
delay(200);
// ソ
tone(SPEAKER, SO_4);
delay(200);
// ミ
tone(SPEAKER, MI_4);
delay(200);
// ド
tone(SPEAKER, DO_4);
delay(200);
// ミ
tone(SPEAKER, MI_4);
delay(200);
// ソ
tone(SPEAKER, SO_4);
delay(200);
// シ
tone(SPEAKER, SI_4);
delay(200);
// 1オクターブ高いド
tone(SPEAKER, DO_5);
delay(200);
// 音を消す
noTone(SPEAKER);
}
// 何もしないで待つ
while( true ) {
}
}
ミニチャレンジ課題
上のスケッチを動作させると、ちょっと気付いたことがあると思います。「ドミソミドミソミドミソシド」というメロディーがつながってしまって、「ドミソミドミソミドミソシドドミソミドミソミドミソシドドミソミドミソミドミソシド」という1つのメロディーになってしまっています。
「ドミソミドミソミドミソシド」を3回繰り返しとして聞こえるように、「ドミソミドミソミドミソシド」のメロディーが終わったら少し時間をおいて次の「ドミソミドミソミドミソシド」が鳴るようにスケッチを変更してみてください。
スケッチが長いですよね
ところで、、、
キッチンタイマーのアラームをメロディーに変更したら、ずいぶんとスケッチが長くなってしまいましたよね。
これって何かいい解決策はないのでしょうか…
更新履歴
日付 | 内容 |
---|---|
2019.11.4 | 新規投稿 |
2021.8.27 | 新サイトデザイン対応 |
2022.2.17 | 誤字訂正 |
単なる誤植だと思いますが、
「普通のド(第4オクターブのド)は440Hz」ではなく
(正)262Hz ではないでしょうか。
いつも分かりやすく、70歳を超えていてもよく理解できます。
ありがとうございます。
otaさま、
ご指摘いただきどうもありがとうございました!
おっしゃる通り、ドは262Hzです。早速修正させていただきました。
自分ではなかなか気づかないのでご指摘いただき大変助かります。
440Hzはラの音ですので全然違いますね…
ところでラの音は440Hzとなっていますが、モーツァルトの時代は432Hzだったという話を聞いたことがあります。ラを432Hzにして昔風のアラームを作ってみるのも面白いかもしれませんね。
コメントいただきどうもありがとうございました。