第39回 チャレンジ課題3

動作開始時にもメロディーを鳴らす

現在のスケッチでは、Arduinoにスケッチを送ると、しばらくしてキッチンタイマーとして動作を開始します。

ただ、キッチンタイマーが動作を始めたのかどうか、タイミングがよくわからないですよね。現在のスケッチでは動作開始時に青色LEDが点灯するので、動作を開始したことはわかりますが、もう少しわかりやすくしたいと思います。

そこで、現在のスケッチに対して、Arduinoの動作開始時に青色LEDを点灯すると同時に、『ドファラ』というそれぞれの音が200msの短いメロディーを鳴らすように変更してみてください。

 

メロディーの変更をやりやすくする

現在のスケッチでは、アラーム音のメロディーは以下のように実現しています。

最初にメロディーの音の数を#defineで定義して、メロディー自体は配列にしています。

#define ALARM_ONKAISUU 13 // アラームメロディーの音の数
uint16_t alarm_melody[] = {DO_4, MI_4, SO_4, MI_4, DO_4, MI_4, SO_4, MI_4, DO_4, MI_4, SO_4, SI_4, DO_5};  // アラームメロディー

次にタイマー設定時間になったら、以下のスケッチでメロディーを演奏しています。

  // メロディー音を3回鳴らす
  for( count=0; count<3; count++) {

    // メロディーを演奏する
    for( oto_bangou=0; oto_bangou<ALARM_ONKAISUU; oto_bangou++ ) {
      tone(SPEAKER, alarm_melody[oto_bangou]);
      delay(200);
    }
    
    // 音を消す
    noTone(SPEAKER);

    // 1.5秒あける
    delay(1500);

  }

このスケッチでメロディーを変更しようとして、例えばメロディーの音の数が増えたり減ったりした場合、変更後のメロディーの音の数を再度数える必要があります。

例えば、現在のメロディーの最後に「ソド」という2つの音階を追加する場合、メロディーの配列は以下のように変更すればよいですが、

uint16_t alarm_melody[] = {DO_4, MI_4, SO_4, MI_4, DO_4, MI_4, SO_4, MI_4, DO_4, MI_4, SO_4, SI_4, DO_5, SO_4, DO_4};

音の数は2音増えたので、以下のように音の数の#defineを13から15に変更する必要があります。

#define ALARM_ONKAISUU 15

このようにメロディーを変更した場合、音の数を数え直して#defineの値を変える、というのはなんだか面倒ですし、メロディーを長くした場合、数え間違えの可能性もありますよね。

そこで、音の数を数えて定義する必要がないようにスケッチを変更したいと思います。

音の数の定義が必要ないようにするやり方はいくつかありますが、このチャレンジ課題ではメロディー配列を以下のようにした場合、どのようなスケッチにすればよいか考えてみてください。

演奏するメロディーは「ドミソミドミソ」にします。また、メロディーの配列を以下のように変更します。

uint16_t alarm_melody[] = {DO_4, MI_4, SO_4, MI_4, DO_4, MI_4, SO_4, 0};

このメロディーの配列のポイントは、最後の音階データを0にしている点です。配列要素が0の場合、音階データの終わり、という意味にしてみます。

音の数を数えて#define定義する必要がないように、このメロディー配列を使用してメロディーを演奏するスケッチを作成してみてください。

ヒント

プログラミングに慣れていないと、何から手をつけてよいかわからないという状態になるかもしれません。そこで、ヒントを一緒考えていきましょう。

前回まで作成したスケッチでは、以下のようにfor文を使用して決まった回数処理を繰り返していました。以下はメロディーを演奏する部分です。13回繰り返すようにfor文を書いています(for文の中を「oto_bangou<13」に書き換えています)。

// メロディーを演奏する
for( oto_bangou=0; oto_bangou<13; oto_bangou++ ) {
  tone(SPEAKER, alarm_melody[oto_bangou]);
  delay(200);
}

このチャレンジ課題では、メロディーの音階の数はあらかじめ数えないので、「for( oto_bangou=0; oto_bangou<13; oto_bangou++)」というように一定回数処理を繰り返すように書くことはできません。

では、以下のメロディーデータをどのような考え方で演奏すればよいのでしょうか。

uint16_t alarm_melody[] = {DO_4, MI_4, SO_4, MI_4, DO_4, MI_4, SO_4, 0};

このメロディーを演奏するには、当然ながら以下のバターンを繰り返すわけですが、

tone(SPEAKER, alarm_melody[添字]);
delay(200);

最後の音階データのみ「0」という特殊なデータになっています。最後以外のメロディーの音階は周波数のデータですので、必ず0以外になっています。ということは、

「alarm_melody[添字]のデータが0以外の間、添字を1ずつ増やしながら

tone(SPEAKER, alarm_melody[添字]);
delay(200);

を繰り返す」

というスケッチを書けばよいわけです。この処理の内容をよく見ると、「〇〇の間、□□を繰り返す」という命令は繰り返し構文のところで出てきましたよね。また「1ずつ増やしながら」というのも変数と演算子のところで出てきましたよね。

あとはじっくりスケッチを考えてみてください。

 

更新履歴

日付 内容
2019.11.13 新規投稿