Arduinoで鳴らすtone回路
クムクムのCPU(ATMEGA32U4)の26番ピン(PD6=Arduino.D12)からは矩形波(BEEP音)を発することができます。
Arduinoのライブラリーでは tone 関数を使います。
このBEEP音は残念ながら1音しか鳴らすことができないため、単純なブーピーという音しか出せませんが、音程はドレミ音階ではなく周波数によって決められるため、組み合わせによってはとても楽しい音を出すことができます。
一昔前のゲーム機(任天堂のファミコン)などではこの音が主流で、この音をうまく使ってスーパーマリオやドラゴンクエストなどのBGMや効果音が作られていました。
現在も、洗濯機や電子レンジ、エアコンのリモコンのボタン操作音などにも使われています。
クムクムでの回路
CPUから直接スピーカーをつないでも、出力が小さすぎて音を鳴らすことができません。
そのため、必ずCPUとスピーカーの間にはオーディオアンプという回路を追加します。
オーディオアンプというと結構たいそうで高級そうに聞こえますが、電子回路用の小さなLSIの中に詰め込んだ簡易的なものもあり、こういった電子製品ではよく使われます。
クムクムではごく一般的なLM386というLSIを使っています。(LM386と同じ機能を持つNJM386)
イメージ回路
※細かくはもう少し小さな部品がいくつか乗りますが、おおよそこんな感じでCPUと基板の上で接続されています。
部品
No | 名称 | 形 | 記号 | 役割 |
① | 半固定抵抗 | ![]() |
![]() |
可変抵抗とも呼ばれ、1番から入った信号2番に出力する量をダイアルを回して変化させることができます。 ここでは音のボリュームとして使っています。 |
② | オーディオアンプ | ![]() |
![]() |
入力された音信号を増幅させて出力します。 増幅度合いは部品の値によって自分で決めることができます。 |
③ | 電解コンデンサー | ![]() |
![]() |
電荷を貯めることができます。 ここでは増幅度を決定することができます。 |
④ | セラミックコンデンサー | ![]() |
![]() |
電荷を貯めることができます。 スピーカが発信するのを抑えます。 |
⑤ | 抵抗 | ![]() |
![]() |
電流を制限したりします。 ④と合わせてスピーカが発信するのを抑えます。 |
⑥ | 電解コンデンサー | ![]() |
![]() |
交流信号を通す役目です。 音の成分だけを抜き取るために使うカップリングコンデンサーと呼びます。 |
⑦ | スピーカー | ![]() |
![]() |
音を鳴らします |
回路はデーターシートを参考に
電子部品には必ずデータシートと言って、その部品の仕様を表す資料がメーカから提供されています。LM386のデータシートはココにあります。
結構いろいろ難しいところがありすべてを理解しようとすると大変ですが、見たいところは、参考回路の部分です。この仕様書では5-10の中段が参考回路図です。
左と右の回路はほとんど変わりません。
変わるところは、右側の回路の中で、赤枠で囲った部分です。
ここを変えることによって、赤線で引いた数字、左側が26dBに対して右側が46dbになっています。
つまり、赤枠の部品(10μの電解コンデンサー)を加えることで右側の回路で出力される音が大きく増幅されます。
自分で組み立ててみたい人へ
これらの部品をひとつづつ集めて組み立てることは結構大変です。
そんな時には、こういった実験回路を部品ごと用意くれているサイトがありますのでそこから購入して組み立てると楽です。
実際には私たちも実験段階ではこういったサイトのキットを使います。
このサイトは1個から誰でも購入することができるので非常に便利です。
秋月電子:ユニバーサル基板でつくる386アンプキット
※半田ごてではんだ付けをしなければいけません
ボリューム:ここでは回路上で使った小さな半固定抵抗の代わりに大きなボリュームを使っています。機能は同じです。
LM386は実績ある回路なので推奨回路のまま作れば間違えなく音を鳴らすことはできますし、実際に製品に組み込む際にも、ごく一般的な電子部品のために入手はしやすいものです。
ですので、量産製品ではよく使うことがありますが、この記事でも紹介したNJM386は日本無線という日本の部品会社の互換部品です。
この部品もLM386と全く同じなのでこれを使うのもいいのですが、LM386は一般的で海外メーカでオーソドックスなのですがNJMは日本製品で海外では入りにくいところもあったりします。私たちが製品を設計する場合、部品が入手しやすいかどうかも結構キーポイントになります。
もっと簡単に鳴らしたい場合
これだけの部品をはんだ付けするのはとても面倒くさいですね。
失敗もあります。
そんな時、とりあえず音が鳴ってくれればいいということであれば、こっと簡単な部品もあります。
実験であれば、こういったものを選定して使ってもいいでしょう。
プログラムで鳴らしてみる
プログラムからはArduinoのtone関数を使います。
[c]
#define BEEP_PIN 12
void setup(){
}
void loop(){
tone(BEEP_PIN,440) ;
delay(1000);
noTone(BEEP_PIN);
delay(500);
}
[/c]
void tone(出力PIN,周波数,出力時間)
Arduinoに用意された標準関数で、出力PINから、周波数(50%のデューティ・サイクル)の高さの音を、出力時間(msec)鳴らします。出力時間(msec)を省略した場合は、出力を止める noTone()関数をコールするまでBEEP音はなり続けます。
※tone関数によって指定できるPINは1つだけに限られます。
出力PIN | 出力PIN番号を指定します |
周波数 | 出力する周波数を設定します |
出力時間 | 何ミリ秒鳴らしたいかを設定します 型:unsigned long 0~4,294,967,295 |
戻り値 | なし |
周波数は試用するボードによって異なります
ボード | 出力周波数 |
Uno,Mega,Leonardo,その他AVR系 | 31Hz~65535Hz |
Zero | 41Hz~275000Hz |
Gemma,Due | 実装なし |
※関数を使用する場合の注意
同時に出力できる音は1音だけですが、複数のピンからアンプやスピーカ等に接続し、切り替えて発音することができます。ただしその場合、必ずnoTone()をコールしてから次のポートのtone()をコールするようにします。
tone()関数は内部でマイコンのタイ―マーを利用します。そのため、同じタイマーを利用したPWMポートの一部が使えなくなったり、他のPWMポートで阻害され音が鳴らない場合が発生します。
その場合は、Arduinoのライブラリー内のソースコードでタイマー割り込みの番号等を変更する必要があります。
※ArduinoMEGA以外ではピン3と11番のPWM出力と競合します。
tone関数で出力した音を停止します。

Qumcumではモータを7個使いPWMとToneが競合しているので競合しないようにTone側のタイマーを変更したプログラムを使っています。
noTone(PIN番号)
tone関数で出力した音を停止します。
PIN番号 | toneを鳴らした出力PIN番号 |
戻り値 | なし |
音階
ドレミファ音階の一例を配列で用意しました。
コピーしてプログラムからご使用ください。
[c]
//—————————————————————————
// 音階表現用周波数テーブル
//—————————————————————————
static int _NoteFreq[84] = {
33, 35, 37, 39, 41, 44, 46, 49, 52, 55, 58, 62,
65, 69, 73, 78, 82, 87, 93, 98, 104, 110, 117, 123,
131, 139, 147, 156, 165, 175, 185, 196, 208, 220, 233, 247,
262, 277, 294, 311, 330, 349, 370, 392, 415, 440, 466, 494,
523, 554, 587, 622, 659, 698, 740, 784, 831, 880, 932, 988,
1047, 1109, 1175, 1245, 1319, 1397, 1480, 1568, 1661, 1760, 1865, 1976,
2093, 2217, 2349, 2489, 2637, 2794, 2960, 3136, 3322, 3520, 3729, 3951,
} ;
[/c]