ATtiny85で音楽を鳴らそう!(tone)

こんにちは、くのへ@MasazaneKunoheです。

今日はATtiny85で音楽を鳴らす方法を紹介します!
toneという命令文を使うもので、これはArduinoと全く同じ方法です。

そのため、Arduinoでtoneを使える人は、全く勉強せずにATtiny85でも使えます。

作るもの

ATtiny85で「おさかな天国」を演奏してみたいと思います!

作り方(概要)

音楽を鳴らすのは簡単です。次の2つのステップで実装できます!

①ブザー(スピーカーでもOK)とATtiny85を組み合わせた回路を作ります

②ATtiny85に「tone」を使ってプログラミングします

詳細

ブザーやスピーカーなどとATtiny85を組み合わせた回路を作ります

toneは普通のデジタルピンで使えます。なので、どのピンを使ってもOKです。
ここでは3番ピン(Pb4ピン)を使った回路を紹介します。

3番ピンにブザーのプラスをセットし、ブザーのもう片方をGNDにセットします。
こんな感じでセットすればOKです。

なお、ブザーには極性があるものがあるので、買う時に気をつけましょう。

私が良く買うPKM13EPYH4000-A0は特に極性に対して注意事項は記載されていないので、プラスマイナスを気にすることなく使えます。(↓これ。画像は秋月電子より

一方、例えばこのブザーは極性があります。(PB04-SE12HPR:画像は秋月電子より
上面にプラスマークが書いていますね。極性があるブザーはプラス極を3番ピンにセットします。

これで回路はヨシ!!

ATtiny85に「tone」を使ってプログラミングします

以下にtoneを使ったサンプルコードを示します。

//ピンの設定
#define soundPin 4 //3番ピン(Pb4ピン)を音の出力ピンとする

//音階データ

//おさかな天国
int scale[] = {
  783,783,783,783,783,783,783,880,987,0,0,0,0,0,880,987,
  1046,0,1046,0,1046,1046,0,987,880,0,0,0,0,0,0,0,

  739,739,739,739,739,739,739,783,880,0,0,0,0,0,880,880,
  783,0,783,0,783,783,0,659,783,0,0,0,0,0,0,0
};

//音の長さ
int time[] ={
  250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250,
  250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250,
  250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250,
  250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250
};

//配列の長さ
int scaleLen = sizeof(scale) / sizeof(int);

//loop用のカウンター
int i=0;


void setup() {
  // put your setup code here, to run once:

  pinMode(soundPin, OUTPUT);

}

void loop() {
  // put your main code here, to run repeatedly:

  SoundMusic();

}

void SoundMusic()
{
  if (i < scaleLen){
    tone(soundPin, scale[i], time[i] * 0.9);  //
    delay(time[i]);
    i++;
  }else{
    //i = 0;
  }   
}

このスケッチをATtiny85に書き込んで、回路に組んでみましょう!
「サカナ♪ サカナ♪ サカナ~♪♪」って流れます!!

コード解説

配列について

楽譜は配列で与えます。
Arduino言語はほぼC言語なので、次のように記載すると配列を作ることが出来ます。

int 変数[] = {XXX,YYY,ZZZ, ...}

これで、XXX、YYY、ZZZ、、、の値を初期値として設定したinteger型の配列変数を作ることが出来ます。

後述の「tone」という命令では、音の長さを指定する必要があり、音階の配列「scale」だけではなく、長さの配列「time」も作ります。

サンプルコードでは、scaleに謎の数字が代入されていますが、この数値については後述の「tone」で解説します。

配列の要素数を調べる方法について

サンプルコードに次の部分は、配列「scale」の中の要素数を調べています。

//配列の長さ
int scaleLen = sizeof(scale) / sizeof(int);

「sizeof(変数)」を使うと、その変数の中のデータの合計ビット数が分かります。
また「sizeof(int)」と書くと、int型変数が使うビット数が分かります。
なので割り算してあげると、中の要素数が分かるというわけです。

配列の中の要素数を調べる方法は、とりあえず上の方法をメモっておけばいいと思います。

配列の要素数は、VBAだとUBound、C#だとscale.Lengthでパッと分かるんですが、ほぼC言語であるArduino言語では上記の方法で取得するのが一般的のようです。

toneについて

toneは音を鳴らす命令文です。toneを使うと指定したピンに所定の周波数の電気的な波を与えることが出来ます。つまりそのピンにブザーをセットするとブザーが鳴ってくれます!

toneは次のように記載します。

tone(出力ピン, 音の周波数, 音の長さ);

これで、指定した出力ピンに、「音の周波数」に記載した周波数の電気的な波が、「音の長さ」に記載した長さの時間だけ送られます。
「音の周波数」の単位はHz(ヘルツ)、「音の長さ」の単位はミリ秒です。

ここで、音の周波数は次のようになっています。

例えば、「サカナ♪ サカナ♪ サカナ~♪♪」は「ソソソ♪ソソソ♪ソラシ~♪♪」なので、下の図の黄色の周波数をtoneに入力すれば、その音を出してくれます!

あとは、「音の長さ」の配列に、長いところは大きい数字、短いところは小さい数字を入れればOKです!!

toneの注意点(delayが要る)

toneには注意点があります。
それは、「toneは『待つ』ことはせず、プログラムはどんどん進んでしまう」という点です。

人間の感覚として、「ドの音を1秒鳴らして、レの音を1秒鳴らして」と命令すれば、まず機械はドを1秒鳴らし、次にレを1秒鳴らしくれるように期待すると思います。

しかし、「tone」という命令は、待ってはくれません。
上述の例で言えば、ドを1秒鳴らすという命令を受け付けますが、すぐにレを1秒鳴らすという命令を受けて上書きします。
すると、ドを一瞬だけ鳴らして、すぐにレを1秒間鳴らす、という挙動をしてしまいます。

そこで、toneの後には「delay(音の長さ)」をつけましょう。
音の長さ分、待ってあげるのです。
これで期待通りの動きになります。

なお、delayは「音の長さ」を待たせ、toneの中の「音の長さ」は0.8~0.95くらい掛けて若干短くしてあげると、1音1音の間に僅かな間が生まれます。こちらの方が人間には自然な感じに聞こえます。(人によって感覚は違うかもw)


今日はATtiny85で音楽を鳴らす方法を紹介しました。

Arduino使いにとっては、全く同じ方法で使えますね!
学習コストが低いって素晴らしい!!

ではまた別の記事で会いましょう。
ではでは~

🦅バサバサ~

参考資料

ロジラボさんのScratchで音楽を作ってコピペできる

敬愛する「ロジラボさん」がScratchで、作った音楽の周波数をコピペできる素晴らしいものを作っておられます。(リンク先

これを使えば、作った音楽の「周波数の楽譜」をコピペできるので、とても便利です!!
おさかな天国もこれを活用させて頂きました!