====SPEAKERドリル==== ライントレーサーに載せてあるスピーカーを使っていきたいと思います。 ここまで来た人はタイマー割り込み(CMT)が理解できていますよね?\\ それではやっていきます。 ===1.とりあえず鳴らしてみよう=== 音ってなんでしょう。皆さんなら波動であることは知っていますよね?スピーカーは電気的な波を受けることによって音波に変換してくれます\\ (構造は面白いので時間があったら調べてみるといいかも)\\ 電気的な波を起こすには一定の時間ON,OFFを繰り返す必要があります。\\ 一定の時間ということでCMT割り込みを使っていきます。\\ 皆さんは1/1000秒(1ms)に一回割り込んでますね?\\ しかし音を鳴らすのにはもっと速く割り込んでもらわないといけません。\\ そこで25倍の速さ、1/25000秒(40μs)で割り込んでみてください。\\ LEDが1秒毎にON,OFFするはずのプログラムが\\ 嫌になるような高速でチカチカするようになるはずです。\\ できましたか?ヒント;initCMTの割り込み周期を変えよう\\ 音の周波数の基準値というのは440Hz(ふつうのラ)だそうです。 楽器を習ったことのある人は知っているかも\\ まず、割り込みの関数内で1ずつ加算される変数sound_countを作ってください。\\ 次に440Hzの電気的な波、つまり1秒間に440回ON/OFFの波を送ってみてください。\\ とりあえずON,OFFのプログラムをwhile(1){}の中に入れてみましょう。\\ ヒント;(ONまたはOFFの時間)=(周期/2) 周期=(1/周波数)\\ 上手くいかない人へ;カウントリセットを忘れていませんか?\\ 出ました?といっても絶対音感の持ち主じゃなきゃわからないですよね?\\スマホのピアノ(鍵盤)アプリとかをダウンロードして、ラの音(これはわかるよね)を出してみてください。\\ ===2.音程、長さを変えてみよう=== 1では永遠に「ラ」の音が出ているプログラムが書けましたね。\\ 音程は周波数の部分を変えるだけです。それぞれの音の周波数は[[http://hp.vector.co.jp/authors/VA046927/scale_freq_table.html|ここ]]で\\ 好きな音、無ければドの音を出してみてください。 またメロディには休符(「そ」とか「皿」みたいなやつ)があります。みなさん知っているようにその期間だけ音を止めます\\ やり方はとても簡単です。ON/OFFをしているプログラムを止めればいいだけです。\\ 次に長さを変えてみたいと思います。\\ いろいろと方法はありますが、一番簡単だと思われる方法でやっていきます。\\ sound_countと同じようにlength_countを用意してください。\\ while(1)の部分をwhile(length_count<=流したい時間(ms)×25)にしてみましょう\\ またそれぞれの音の終わりには一瞬、休符を入れてみるといいです。\\ 音楽チョー得意だぜって人はいいですが、そうでない人は下のをやってみてください\\ 「ソ」200msを3回、「レ#」1000msを1回、「ファ」200msを3回、「レ」1000msを1回\\ きっと皆さんが知っている曲が流れると思います。\\ くれぐれもカウントリセットを忘れずに!!\\ ===ちょっとブレイク=== 音の長さは明確に決められている場合が多いです。曲によって違いますが一分間に四分音符が50~300くらいだそうです。\\ 上でやってもらった曲では一分間に四分音符が168~216回だそうです。\\ ちなみにソとファは八分音符、レ#とレが四分音符×2.5です。 それを考慮して上の交響曲を流してみてください。\\ ===3.周波数を定義しよう=== 2では好きなメロディを流すことができるようになりましたね?\\ えっメロディ流したくても音がわからない?――音感がある人に耳コピしてもらいましょう。\\ 人によっては知っているかもしれませんが、プログラムには定義文というものがあります。\\ 定義文は次のように書くことが出来ます。\\ #define (定義名) プログラム \\ これはプログラムの一番最初に書いてください。\\ 例えば #define la0 440 のように書いてみます。(laはラ、0は基準のオクターブ)\\ するとla0に440という数が"定義"されました\\ 以降、「ふつうのラの周波数はえっーーーと440Hzだ」ではなく\\ 「ふつうのラの周波数はla0」と調べたり思い出す時間、手間を省けます\\ ちなみにドレミはイタリア語で「do re mi fa sol la si do」です。\\ 他にもモーターを回す際にポートを調べたり、覚えたりする手間が省けます。その際は\\ #define Motor_Right_ON (PE.DRL.BIT.B0=1; PE.DRL.BIT.B1=0;)\\ のようにします。以降はMotor_Right_ON;とプログラムに入力するだけで\\ 右のモーターが回ってくれます。なんか直感的でいいですよね?\\ 注意:次の関数と違い#defineが書いてある一行しか定義されません。\\ ===4.音の関数化=== 3,4で音が簡単に流せるようになりましたね?人によっては5,6行でひとつの音が流せているかもしれません。\\ しかし、関数化することによってたった一行で音やメロディを流せるようになります。\\ 今まで挙げてきた音のパラメータ(変数要素)ってなんでしょう?――音程(周波数)、長さですよね?\\ 試しにsound_playerという関数を作ってみましょう。戻り値はいりません。\\ 中身は当然今までやってきた、一つの音を出すプログラムです。\\ 次に引数としてfreq(float型)、length_ms(int型)を用意しそれぞれ周波数の数と長さの数があるところに置換してみてください。 これで完成です。 main関数に sound_player(do0,1000);とでも書いて実行してみましょう。\\ 一行で音が流せましたね?\\ メロディを一行で流すこともできますが少し難易度が高いです。 void music_player(int sound[255],int length[255])とし、その中でmelo_countという変数を作ります\\ そしてsound_player関数をmelo_countでfor文を使って、ループさせます。 ===5.動作中の音楽再生(マルチタスク)=== 項目1~4で自由にメロディーが鳴らせるようになりましたね。 ここまででも十分楽しいですが、今のままでは音楽を流している間、他の動作は出来ません。ライントレースをしながらメロディーを流したいという人もいますね。 そこで、マルチタスクのプログラムのヒントを書いていきます。 項目1の「ラ(440Hz)の音を鳴らす」を例にとります。 先ほどの復習ですが、 まず割り込みの関数内で1ずつ加算される変数sound_countを用意します。 そして、メイン関数で、 while(1){}のかっこの中に1秒間に440回ON/OFFするプログラムを書きましたね。 このままではメイン関数ではラの音を鳴らす以外のことはできません。 では、次のことをしてみてください。 while(1){}のかっこの中のON/OFFするプログラムの「while」を「if」に変える。そのプログラムを切り取って、割り込み関数の中に移す。 どうですか。上手く行けばラの音がなるはずです。 鳴ったところでプログラムを見返してみると、メイン関数ではやることが無くなっているはずです。割り込み関数ではラの音を鳴らしています。ここからがんばって、一つの音を出す関数、メロディーを流す関数を作りましょう。 完成すると、メイン関数ではなにもせず、割り込み関数だけでメロディーがならせるようになるはずです。 ここまで来れば完成です。 ライントレーサーのプログラムと合体させてもトレースと平行してメロディーが鳴らせますね。