ガイド · 読了まで10分

Jingle Bells(ジングルベル)のArduinoコード:ブザーで鳴らすクリスマスソング4曲

Jingle Bells(ジングルベル)のArduinoコードに加えて、おめでとうクリスマス、きよしこの夜、ひいらぎかざろうの3曲もパッシブブザーで鳴らします。音名の表、テンポの計算、millis()を使ったLED付きプレーヤーも紹介します。

ArduinoでJingle Bells(ジングルベル)を鳴らすのに必要なのは、パッシブブザーとtone()関数だけです。各音の周波数と長さを配列に書いておけば、Arduinoがそれを1つずつブザーに送ります。この記事では、ジングルベル、おめでとうクリスマス(We Wish You a Merry Christmas)、きよしこの夜(Silent Night)、ひいらぎかざろう(Deck the Halls)の音と長さの配列を紹介します。耳コピではなく、楽譜から起こした正確なものです。4曲とも100年以上前から歌われている伝統曲なので、著作権を気にせずどんなプロジェクトにも使えます。

まずは1曲だけの短いスケッチから始め、次に4曲を順番に演奏し、音に合わせて2個のLEDを点滅させ、ボタンで曲を切り替えるオルゴールに進みます。2つ目のスケッチはdelay()ではなくmillis()を使うので、曲の演奏中もボタン、センサー、LEDテープなどほかの処理を続けられます。最後に、同じメロディーをESP32のタッチ式クリスマスカードと、Raspberry Pi PicoのMicroPythonに移植します。

Arduinoでクリスマスソングを鳴らすパッシブブザー
パッシブブザーはtone()で与えた周波数をそのまま鳴らすので、メロディーに向いています。

必要なのはアクティブブザー?それともパッシブブザー?

アクティブブザーは内部に発振回路を持っていて、5 Vを加えると常に同じ高さの音で鳴るため、メロディーは演奏できません。パッシブブザーは小さなスピーカーのようなもので、Arduinoのピンがオン・オフを繰り返す周波数で音を出します。見分ける簡単な方法は、ブザーを3〜5 Vの電池に一瞬当ててみることです。ピーと鳴り続ければアクティブ、カチッと1回だけ鳴ればパッシブです。アクティブ型は上面に白いシールが貼られていて底面がふさがっていることが多く、パッシブ型は裏側に緑色の基板が見えます。詳しくは「ブザーとは?」を参照してください。

特徴アクティブブザーパッシブブザー
内蔵の発振回路ありなし
メロディーを演奏できる?いいえ、1つの音だけはい、tone()でどの音も
駆動に使う命令digitalWrite()tone(pin, 周波数, 時間)
電池に当てたときピーと鳴り続けるカチッと1回
最も大きく鳴る範囲固定(通常2〜2.5 kHz)約2〜4 kHz(共振)

配線:ブザー、2個のLED、ボタン

部品Arduino UnoESP32Raspberry Pi Pico
パッシブブザー +D8GPIO 25GP15
パッシブブザー −GNDGNDGND
LED 1(220 Ωの抵抗付き)D6GPIO 26GP14
LED 2(220 Ωの抵抗付き)D7GPIO 27GP13
ボタン(もう一方の足はGND)D2GPIO 4GP2
タッチ用のアルミホイル―GPIO 32(T9)―
Unoではtone()がTimer2を使うため、曲の演奏中はD3とD11でanalogWrite()が動作しません。これらのピンにLEDをつないで明るさを調整しようとすると、ちらついたり、まったく光らなかったりします。ブザーをピンに直接つなぐのは問題ありませんが、8 Ωのスピーカーは絶対にピンへ直接つながないでください。下の「音を大きく、きれいにする」の節にあるトランジスタ回路を使います。

音の周波数:このクリスマスソングで使う14の音

西洋音楽では1オクターブを12の半音に分け、半音1つ上がるごとに周波数は2の12乗根、約1.0595倍になります。基準の音A4(ラ)は440 Hzで、MIDIノート番号nの音の周波数はf = 440 × 2^((n − 69) / 12)で求められます。たとえばC5(ド)はMIDI 72なので、440 × 2^(3/12) = 523.25 Hzです。1オクターブ上がると周波数はちょうど2倍になるので、C6は1047 Hzです。小型のパッシブブザーは500 Hz未満では音が弱いため、4曲とも第5・第6オクターブの音域に移しました。表にはコードで使うすべての音を載せています。

音名ドレミ周波数(Hz)コードの定数
B4シ494NOTE_B4
C5ド523NOTE_C5
D5レ587NOTE_D5
E5ミ659NOTE_E5
F5ファ698NOTE_F5
F#5ファ♯740NOTE_FS5
G5ソ784NOTE_G5
A5ラ880NOTE_A5
A#5 / Bb5シ♭932NOTE_AS5
B5シ988NOTE_B5
C6ド1047NOTE_C6
D6レ1175NOTE_D6
E6ミ1319NOTE_E6
F6ファ1397NOTE_F6

テンポと音の長さ

長さを1つずつミリ秒で書く代わりに、最も短い音である8分音符を単位にしました。1は8分音符、2は4分音符、3は付点4分音符、4は2分音符、6は付点2分音符、8は全音符です。テンポは1分間の4分音符の数(BPM)で、4分音符の長さは60000 / BPMミリ秒、8分音符はその半分です。120 BPMなら4分音符が500 ms、8分音符が250 msです。曲の速さを変えたいときは、配列には触れずに8分音符の長さだけを変えます。各音は長さの90%だけ鳴らし、残りの10%は無音にしているので、同じ音が続く部分(ジングルベルで3つ続くミなど)が1つの長い音にくっつきません。

曲拍子テンポ8分音符(ms)4分音符(ms)音符の数
ジングルベル(サビ)4/4120 BPM25050051
おめでとうクリスマス3/4150 BPM20040030
きよしこの夜3/475 BPM40080046
ひいらぎかざろう4/4約130 BPM23046068

最初のスケッチ:ジングルベルのサビ

  1. パッシブブザーの+端子をD8に、もう一方をGNDにつなぎます。
  2. Arduino IDEを開いて下のコードを貼り付け、ボードにArduino Unoを選択します。
  3. 書き込むと、ボードの起動と同時にサビが1回演奏されます。もう一度聴くにはリセットボタンを押します。
  4. 遅すぎたり速すぎたりする場合はEIGHTH_MSを変更します。200にすると速く、300にすると遅くなります。
C++ (Arduino IDE)
1// Jingle Bells nakaratı - pasif buzzer D8 / Jingle Bells chorus - passive buzzer on D8
2#define NOTE_C5 523
3#define NOTE_D5 587
4#define NOTE_E5 659
5#define NOTE_F5 698
6#define NOTE_G5 784
7
8const int BUZZER_PIN = 8;      // pasif buzzer + ucu / passive buzzer + lead
9const int EIGHTH_MS = 250;     // 120 BPM: dörtlük 500 ms, sekizlik 250 ms / quarter 500 ms, eighth 250 ms
10
11const int melody[] = {
12  NOTE_E5, NOTE_E5, NOTE_E5,   NOTE_E5, NOTE_E5, NOTE_E5,
13  NOTE_E5, NOTE_G5, NOTE_C5, NOTE_D5,   NOTE_E5,
14  NOTE_F5, NOTE_F5, NOTE_F5, NOTE_F5,   NOTE_F5, NOTE_E5, NOTE_E5, NOTE_E5, NOTE_E5,
15  NOTE_E5, NOTE_D5, NOTE_D5, NOTE_E5,   NOTE_D5, NOTE_G5,
16  NOTE_E5, NOTE_E5, NOTE_E5,   NOTE_E5, NOTE_E5, NOTE_E5,
17  NOTE_E5, NOTE_G5, NOTE_C5, NOTE_D5,   NOTE_E5,
18  NOTE_F5, NOTE_F5, NOTE_F5, NOTE_F5,   NOTE_F5, NOTE_E5, NOTE_E5, NOTE_E5, NOTE_E5,
19  NOTE_G5, NOTE_G5, NOTE_F5, NOTE_D5,   NOTE_C5
20};
21// süreler sekizlik cinsinden: 1 = sekizlik, 2 = dörtlük, 3 = noktalı dörtlük, 4 = ikilik, 8 = birlik
22// lengths in eighths: 1 = eighth, 2 = quarter, 3 = dotted quarter, 4 = half, 8 = whole
23const byte beats[] = {
24  2, 2, 4,   2, 2, 4,
25  2, 2, 3, 1,   8,
26  2, 2, 3, 1,   2, 2, 2, 1, 1,
27  2, 2, 2, 2,   4, 4,
28  2, 2, 4,   2, 2, 4,
29  2, 2, 3, 1,   8,
30  2, 2, 3, 1,   2, 2, 2, 1, 1,
31  2, 2, 2, 2,   8
32};
33
34void setup() {
35  int count = sizeof(melody) / sizeof(melody[0]);   // 51 nota / 51 notes
36  for (int i = 0; i < count; i++) {
37    int duration = beats[i] * EIGHTH_MS;
38    tone(BUZZER_PIN, melody[i], duration * 9 / 10);  // notalar arasında %10 boşluk / 10% gap between notes
39    delay(duration);
40  }
41  noTone(BUZZER_PIN);
42}
43
44void loop() {
45  // bir kez çalar; tekrar için reset tuşuna bas / plays once, press reset to replay
46}

スケッチでは2つの並列配列を使います。melodyには音の周波数、beatsには同じ順番で各音の長さ(8分音符単位)が入っています。ループは音ごとにtone()で音を出し、delay()で音の長さ分だけ待ちます。tone()は3番目の引数に時間を渡すと、その時間で自動的に音を止めます。ここでは音の長さの90%を渡しているので、音と音の間に短い息継ぎが入ります。2つの配列の要素数は必ず同じにしてください。片方に音を追加してもう片方に長さを追加し忘れると、メロディーがずれ、配列の終わりより先にある無関係なメモリの値が演奏されてしまいます。配列内の空白は小節線の位置に合わせてあるので、楽譜と見比べやすくなっています。

4曲の音の配列

下の表は、各曲の調と最初のフレーズの音を示しています。耳でコードを確認するときに役立ちます。ダッシュ(–)は小節線、ドット(.)は付点音符です。おめでとうクリスマスは弱起(アウフタクト、anacrusis)で始まり、最初のC5は1小節目の前にある4分音符1つです。きよしこの夜はとてもゆっくりと伸びやかな曲なので、最後のC5は8分音符12個分、つまり丸々2小節伸ばしました。ひいらぎかざろうで唯一のシャープは、上がっていく「fa-la-la」(ファラララ)の部分にあるファ♯(F#5)です。

曲調最初のフレーズの音注意点
ジングルベルハ長調ミ ミ ミ – ミ ミ ミ – ミ ソ ド. レ – ミ「all the way」の部分は付点4分音符+8分音符
おめでとうクリスマスヘ長調ド – ファ ファ ソ ファ ミ – レ レ レ3/4拍子、シ♭(A#5)を使う
きよしこの夜ハ長調(1オクターブ上)ソ. ラ ソ – ミ – ソ. ラ ソ – ミゆっくりしたテンポ、付点2分音符
ひいらぎかざろうハ長調ソ. ファ ミ レ – ド レ ミ ド「fa-la-la」の8分音符、ファ♯(F#5)

millis()で動くLED付きクリスマスソングプレーヤー(4曲+ボタン)

次は4曲すべてを1つのスケッチにまとめます。音は{周波数, 長さ}の組からなるNote構造体に入れ、PROGMEMでフラッシュメモリに保存します。UnoのRAMはわずか2 KBなので、195個の音をRAMに置かずフラッシュから読むのはよい習慣です。LEDは音ごとに入れ替わり、D2のボタンは内部プルアップを使い、押すと次の曲に進みます。曲が終わると1.5秒の無音のあと、次の曲が始まります。

C++ (Arduino IDE)
1// 4 Noel şarkısı: millis ile çalar, LED'ler notaya göre yanar, buton sonraki şarkıya geçer
2// 4 Christmas songs: millis-based player, LEDs follow the notes, button skips to the next song
3#define REST     0
4#define NOTE_B4  494
5#define NOTE_C5  523
6#define NOTE_D5  587
7#define NOTE_E5  659
8#define NOTE_F5  698
9#define NOTE_FS5 740
10#define NOTE_G5  784
11#define NOTE_A5  880
12#define NOTE_AS5 932
13#define NOTE_B5  988
14#define NOTE_C6  1047
15#define NOTE_D6  1175
16#define NOTE_E6  1319
17#define NOTE_F6  1397
18
19#if defined(ESP32)
20const int BUZZER_PIN = 25;               // ESP32 pinleri / ESP32 pins
21const int LED_PINS[2] = {26, 27};
22const int BUTTON_PIN = 4;
23#else
24const int BUZZER_PIN = 8;                // Arduino Uno pinleri / Arduino Uno pins
25const int LED_PINS[2] = {6, 7};
26const int BUTTON_PIN = 2;
27#endif
28
29struct Note { uint16_t freq; uint8_t len; };   // len: sekizlik sayısı / length in eighths
30
31// Jingle Bells (Do majör, 4/4) / (C major, 4/4)
32const Note JINGLE[] PROGMEM = {
33  {NOTE_E5,2},{NOTE_E5,2},{NOTE_E5,4}, {NOTE_E5,2},{NOTE_E5,2},{NOTE_E5,4},
34  {NOTE_E5,2},{NOTE_G5,2},{NOTE_C5,3},{NOTE_D5,1}, {NOTE_E5,8},
35  {NOTE_F5,2},{NOTE_F5,2},{NOTE_F5,3},{NOTE_F5,1}, {NOTE_F5,2},{NOTE_E5,2},{NOTE_E5,2},{NOTE_E5,1},{NOTE_E5,1},
36  {NOTE_E5,2},{NOTE_D5,2},{NOTE_D5,2},{NOTE_E5,2}, {NOTE_D5,4},{NOTE_G5,4},
37  {NOTE_E5,2},{NOTE_E5,2},{NOTE_E5,4}, {NOTE_E5,2},{NOTE_E5,2},{NOTE_E5,4},
38  {NOTE_E5,2},{NOTE_G5,2},{NOTE_C5,3},{NOTE_D5,1}, {NOTE_E5,8},
39  {NOTE_F5,2},{NOTE_F5,2},{NOTE_F5,3},{NOTE_F5,1}, {NOTE_F5,2},{NOTE_E5,2},{NOTE_E5,2},{NOTE_E5,1},{NOTE_E5,1},
40  {NOTE_G5,2},{NOTE_G5,2},{NOTE_F5,2},{NOTE_D5,2}, {NOTE_C5,8}
41};
42
43// We Wish You a Merry Christmas (Fa majör, 3/4) / (F major, 3/4)
44const Note WE_WISH[] PROGMEM = {
45  {NOTE_C5,2},
46  {NOTE_F5,2},{NOTE_F5,1},{NOTE_G5,1},{NOTE_F5,1},{NOTE_E5,1}, {NOTE_D5,2},{NOTE_D5,2},{NOTE_D5,2},
47  {NOTE_G5,2},{NOTE_G5,1},{NOTE_A5,1},{NOTE_G5,1},{NOTE_F5,1}, {NOTE_E5,2},{NOTE_C5,2},{NOTE_C5,2},
48  {NOTE_A5,2},{NOTE_A5,1},{NOTE_AS5,1},{NOTE_A5,1},{NOTE_G5,1}, {NOTE_F5,2},{NOTE_D5,2},{NOTE_C5,1},{NOTE_C5,1},
49  {NOTE_D5,2},{NOTE_G5,2},{NOTE_E5,2}, {NOTE_F5,6}
50};
51
52// Silent Night (Do majör, 3/4, bir oktav yukarı) / (C major, 3/4, one octave up)
53const Note SILENT[] PROGMEM = {
54  {NOTE_G5,3},{NOTE_A5,1},{NOTE_G5,2}, {NOTE_E5,6}, {NOTE_G5,3},{NOTE_A5,1},{NOTE_G5,2}, {NOTE_E5,6},
55  {NOTE_D6,4},{NOTE_D6,2}, {NOTE_B5,6}, {NOTE_C6,4},{NOTE_C6,2}, {NOTE_G5,6},
56  {NOTE_A5,4},{NOTE_A5,2}, {NOTE_C6,3},{NOTE_B5,1},{NOTE_A5,2}, {NOTE_G5,3},{NOTE_A5,1},{NOTE_G5,2}, {NOTE_E5,6},
57  {NOTE_A5,4},{NOTE_A5,2}, {NOTE_C6,3},{NOTE_B5,1},{NOTE_A5,2}, {NOTE_G5,3},{NOTE_A5,1},{NOTE_G5,2}, {NOTE_E5,6},
58  {NOTE_D6,4},{NOTE_D6,2}, {NOTE_F6,3},{NOTE_D6,1},{NOTE_B5,2}, {NOTE_C6,6}, {NOTE_E6,6},
59  {NOTE_C6,2},{NOTE_G5,2},{NOTE_E5,2}, {NOTE_G5,3},{NOTE_F5,1},{NOTE_D5,2}, {NOTE_C5,12}
60};
61
62// Deck the Halls (Do majör, 4/4) / (C major, 4/4)
63const Note DECK[] PROGMEM = {
64  {NOTE_G5,3},{NOTE_F5,1},{NOTE_E5,2},{NOTE_D5,2}, {NOTE_C5,2},{NOTE_D5,2},{NOTE_E5,2},{NOTE_C5,2},
65  {NOTE_D5,1},{NOTE_E5,1},{NOTE_F5,1},{NOTE_D5,1},{NOTE_E5,3},{NOTE_D5,1}, {NOTE_C5,2},{NOTE_B4,2},{NOTE_C5,4},
66  {NOTE_G5,3},{NOTE_F5,1},{NOTE_E5,2},{NOTE_D5,2}, {NOTE_C5,2},{NOTE_D5,2},{NOTE_E5,2},{NOTE_C5,2},
67  {NOTE_D5,1},{NOTE_E5,1},{NOTE_F5,1},{NOTE_D5,1},{NOTE_E5,3},{NOTE_D5,1}, {NOTE_C5,2},{NOTE_B4,2},{NOTE_C5,4},
68  {NOTE_D5,3},{NOTE_E5,1},{NOTE_F5,2},{NOTE_D5,2}, {NOTE_E5,3},{NOTE_F5,1},{NOTE_G5,2},{NOTE_D5,2},
69  {NOTE_E5,1},{NOTE_FS5,1},{NOTE_G5,2},{NOTE_A5,1},{NOTE_B5,1},{NOTE_C6,2}, {NOTE_B5,2},{NOTE_A5,2},{NOTE_G5,4},
70  {NOTE_G5,3},{NOTE_F5,1},{NOTE_E5,2},{NOTE_D5,2}, {NOTE_C5,2},{NOTE_D5,2},{NOTE_E5,2},{NOTE_C5,2},
71  {NOTE_A5,1},{NOTE_A5,1},{NOTE_A5,1},{NOTE_A5,1},{NOTE_G5,3},{NOTE_F5,1}, {NOTE_E5,2},{NOTE_D5,2},{NOTE_C5,4}
72};
73
74struct Song { const Note* notes; uint8_t count; uint16_t eighthMs; };
75const Song SONGS[] = {
76  {JINGLE,  sizeof(JINGLE)  / sizeof(Note), 250},   // 120 BPM
77  {WE_WISH, sizeof(WE_WISH) / sizeof(Note), 200},   // 150 BPM
78  {SILENT,  sizeof(SILENT)  / sizeof(Note), 400},   // 75 BPM
79  {DECK,    sizeof(DECK)    / sizeof(Note), 230}    // yaklaşık 130 BPM / about 130 BPM
80};
81const uint8_t SONG_COUNT = sizeof(SONGS) / sizeof(Song);
82const unsigned long SONG_GAP_MS = 1500;   // şarkılar arası sessizlik / silence between songs
83
84uint8_t song = 0;
85int noteIndex = -1;                       // -1: şarkı başlamadı / song not started
86unsigned long noteStart = 0;
87unsigned long noteLength = 0;
88bool lastButton = HIGH;
89unsigned long lastPress = 0;
90
91void ledsOff() {
92  digitalWrite(LED_PINS[0], LOW);
93  digitalWrite(LED_PINS[1], LOW);
94}
95
96void startNote() {
97  Note n;
98  memcpy_P(&n, &SONGS[song].notes[noteIndex], sizeof(Note));   // flash'tan oku / read from flash
99  noteLength = (unsigned long)n.len * SONGS[song].eighthMs;
100  if (n.freq != REST) {
101    tone(BUZZER_PIN, n.freq, noteLength * 9 / 10);              // %10 boşluk / 10% gap
102    digitalWrite(LED_PINS[noteIndex % 2], HIGH);                // LED'ler sırayla / LEDs alternate
103    digitalWrite(LED_PINS[(noteIndex + 1) % 2], LOW);
104  } else {
105    noTone(BUZZER_PIN);
106    ledsOff();
107  }
108  noteStart = millis();
109}
110
111void nextSong() {
112  noTone(BUZZER_PIN);
113  ledsOff();
114  song = (song + 1) % SONG_COUNT;
115  noteIndex = 0;
116  startNote();
117}
118
119void setup() {
120  pinMode(LED_PINS[0], OUTPUT);
121  pinMode(LED_PINS[1], OUTPUT);
122  pinMode(BUTTON_PIN, INPUT_PULLUP);      // buton GND'ye / button to GND
123  noteIndex = 0;
124  startNote();
125}
126
127void loop() {
128  unsigned long now = millis();
129
130  // Buton: düşen kenar + 250 ms kilit / button: falling edge + 250 ms lockout
131  bool button = digitalRead(BUTTON_PIN);
132  if (lastButton == HIGH && button == LOW && now - lastPress > 250) {
133    lastPress = now;
134    nextSong();
135  }
136  lastButton = button;
137
138  // Nota süresi doldu mu? / has the note finished?
139  if (now - noteStart >= noteLength) {
140    noteIndex++;
141    if (noteIndex < SONGS[song].count) {
142      startNote();
143    } else if (noteIndex == SONGS[song].count) {   // şarkı bitti: ara ver / song over: pause
144      ledsOff();
145      noteLength = SONG_GAP_MS;
146      noteStart = now;
147    } else {
148      nextSong();                                  // aradan sonra sıradaki şarkı / next song after the pause
149    }
150  }
151}

コードの中心はloop()内の時間チェックです。millis() − noteStartが音の長さを超えたら次の音を始め、超えていなければloopは待たずに先へ進みます。こうすることで毎回ボタンが読み取られ、押したのを見逃しません。delay()を使っていたら、きよしこの夜の最後の4.8秒の音の間、ボタンはまったく反応しなかったでしょう。memcpy_P()は音をフラッシュからRAMの一時変数にコピーします。曲が終わるとnoteIndexが音の数と等しくなり、この値を「休止」状態として使います。休止時間が過ぎるとnextSong()が呼ばれます。コンパイルしたスケッチはUnoでフラッシュ約3.9 KB、RAM 67バイトを使います。delay()ではなくmillis()を選んだ理由を詳しく知りたい場合は、「millis()とdelay()の違い」を読んでください。

曲を1オクターブ上げるには、tone()の行をtone(BUZZER_PIN, n.freq * 2, ...)のようにして周波数を2倍にするだけです。パッシブブザーは2〜4 kHz付近で最も大きく鳴るので、この小さな変更で音がはっきり大きくなります。ただし、きよしこの夜のようにもともと高い音まで上がる曲では、音が甲高くなって耳障りに感じることがあります。

ESP32でクリスマスソング:タッチで鳴るクリスマスカード

上のプレーヤーのスケッチは、ESP32でもそのままコンパイルできます。#if defined(ESP32)のブロックがピンを自動的にGPIO 25、26、27、4に切り替えます。ESP32コアの2.xと3.xにはtone()があり、内部ではLEDC PWMユニットを使っています。ESP32のピンは3.3 Vを出力するため、音はUnoより少し小さくなります。下の短いスケッチはESP32のタッチピンを使います。GPIO 32につないだアルミホイルの星に指で触れると、ジングルベルの最初のフレーズが流れ、LEDが点灯します。コードは起動時に触れていない状態の値を測り、しきい値を自分で決めます。タッチピンについて詳しくは「ESP32のタッチピン」を参照してください。

C++ (Arduino IDE)
1// ESP32 dokunmatik Noel kartı: folyo yıldıza dokununca Jingle Bells çalar
2// ESP32 touch Christmas card: touch the foil star and Jingle Bells plays
3const int BUZZER_PIN = 25;     // pasif buzzer / passive buzzer
4const int LED_PIN = 26;        // yıldızın LED'i / star LED
5const int TOUCH_PIN = 32;      // T9: folyoya giden kablo / T9: wire to the foil
6
7const int EIGHTH_MS = 250;
8const int melody[] = {659, 659, 659, 659, 659, 659, 659, 784, 523, 587, 659};   // E E E, E E E, E G C D E
9const byte beats[] = {2, 2, 4, 2, 2, 4, 2, 2, 3, 1, 8};
10int threshold = 0;
11
12void setup() {
13  Serial.begin(115200);
14  pinMode(LED_PIN, OUTPUT);
15  long sum = 0;
16  for (int i = 0; i < 20; i++) {           // dokunmadan ortalama al / average while untouched
17    sum += touchRead(TOUCH_PIN);
18    delay(20);
19  }
20  threshold = (sum / 20) * 7 / 10;         // eşik: ortalamanın %70'i / threshold: 70% of the average
21  Serial.printf("Esik / threshold: %d\n", threshold);
22}
23
24void loop() {
25  if (touchRead(TOUCH_PIN) < threshold) {  // dokununca değer düşer / the value drops when touched
26    digitalWrite(LED_PIN, HIGH);
27    for (int i = 0; i < 11; i++) {
28      int duration = beats[i] * EIGHTH_MS;
29      tone(BUZZER_PIN, melody[i], duration * 9 / 10);
30      delay(duration);
31    }
32    noTone(BUZZER_PIN);
33    digitalWrite(LED_PIN, LOW);
34    delay(1000);                           // art arda tetiklenmesin / avoid instant retrigger
35  }
36}

Raspberry Pi PicoとMicroPythonでクリスマスソング

Picoにはtone()がありませんが、machine.PWMで同じことができます。freq()で音の周波数を、duty_u16(32768)で50%のデューティ比を設定します。この比率でブザーが最も大きく鳴ります。duty_u16(0)で音が止まります。スクリプトは2曲を順番に演奏し、GP2のボタンを押すと演奏中の曲が止まって次の曲に進みます。残りの2曲も、Arduinoのスケッチの数値を使って同じ形式で追加できます。周波数も長さもまったく同じです。MicroPythonが初めてなら、まず「Raspberry Pi Picoとは?」にあるThonnyのセットアップから始めてください。

MicroPython
1# Raspberry Pi Pico (MicroPython): Jingle Bells + We Wish You a Merry Christmas
2from machine import Pin, PWM
3import time
4
5buzzer = PWM(Pin(15))                 # pasif buzzer GP15 / passive buzzer on GP15
6leds = [Pin(14, Pin.OUT), Pin(13, Pin.OUT)]
7button = Pin(2, Pin.IN, Pin.PULL_UP)  # buton GP2 -> GND / button GP2 -> GND
8
9C5, D5, E5, F5, G5, A5, AS5 = 523, 587, 659, 698, 784, 880, 932
10
11JINGLE = [(E5,2),(E5,2),(E5,4),(E5,2),(E5,2),(E5,4),(E5,2),(G5,2),(C5,3),(D5,1),(E5,8),
12          (F5,2),(F5,2),(F5,3),(F5,1),(F5,2),(E5,2),(E5,2),(E5,1),(E5,1),
13          (E5,2),(D5,2),(D5,2),(E5,2),(D5,4),(G5,4),
14          (E5,2),(E5,2),(E5,4),(E5,2),(E5,2),(E5,4),(E5,2),(G5,2),(C5,3),(D5,1),(E5,8),
15          (F5,2),(F5,2),(F5,3),(F5,1),(F5,2),(E5,2),(E5,2),(E5,1),(E5,1),
16          (G5,2),(G5,2),(F5,2),(D5,2),(C5,8)]
17WE_WISH = [(C5,2),(F5,2),(F5,1),(G5,1),(F5,1),(E5,1),(D5,2),(D5,2),(D5,2),
18           (G5,2),(G5,1),(A5,1),(G5,1),(F5,1),(E5,2),(C5,2),(C5,2),
19           (A5,2),(A5,1),(AS5,1),(A5,1),(G5,1),(F5,2),(D5,2),(C5,1),(C5,1),
20           (D5,2),(G5,2),(E5,2),(F5,6)]
21SONGS = [(JINGLE, 250), (WE_WISH, 200)]   # (notalar, sekizlik ms) / (notes, eighth ms)
22
23def play(notes, eighth_ms):
24    for i, (freq, length) in enumerate(notes):
25        duration = length * eighth_ms
26        leds[i % 2].on()
27        leds[(i + 1) % 2].off()
28        if freq:
29            buzzer.freq(freq)
30            buzzer.duty_u16(32768)        # %50 doluluk = en yüksek ses / 50% duty = loudest
31        time.sleep_ms(duration * 9 // 10)
32        buzzer.duty_u16(0)                # %10 sessizlik / 10% silence
33        time.sleep_ms(duration // 10)
34        if button.value() == 0:           # basılırsa şarkıyı kes / stop the song on press
35            break
36    for led in leds:
37        led.off()
38
39song = 0
40while True:
41    play(*SONGS[song])
42    song = (song + 1) % len(SONGS)
43    time.sleep_ms(1500)

音を大きく、きれいにする

  • トランジスタとスピーカー:ピンから1 kΩの抵抗を通してNPNトランジスタ(2N2222、BC337)のベースにつなぎ、スピーカーを5 Vとコレクタの間に、エミッタをGNDに接続します。小型の8 Ωスピーカーはブザーよりずっと厚みのある音になります。47〜100 Ωの直列抵抗で電流を制限します。
  • 共振の範囲:小型の圧電ブザーは2〜4 kHz付近で最も大きく鳴ります。メロディーを1オクターブ上げると、トランジスタほどではありませんが、音がはっきり大きくなります。
  • 箱の効果:ブザーを段ボール箱やオーナメントボールの中に、穴を外に向けて入れると、自然に音が大きくなります。
  • 音を小さくするには:夜に動かすプロジェクトでは、ブザーに100〜470 Ωの抵抗を直列に入れます。音量は下がり、メロディーはそのまま保たれます。
  • 1音しか出せない:Unoのtone()は同時に1つのピンでしか音を出せません。和音や2声の音楽には、DFPlayer MiniのようなMP3モジュールが向いています。選択肢は「Arduinoの音と音楽のプロジェクト」で比較しています。

よくある問題と対処法

症状原因対処法
いつも同じピー音しか鳴らないアクティブブザーを使っているパッシブブザーに交換する。電池に当てるとカチッと鳴るものが正解
メロディーが分からない、音がずれているmelodyとbeatsの配列の長さが違う要素数をそろえ、小節ごとに確認する
同じ音が続くと1つの長い音に聞こえる音と音の間に無音がないtone()の時間を音の長さの90%にする
D3またはD11のLEDがちらつくtone()がTimer2を使っているLEDをD6やD7など別のピンに移す
1回押すと何曲も飛ぶボタンのチャタリング立ち下がりエッジを検出し、250 msの不感時間を入れる
ESP32でエラー:'tone' was not declared(宣言されていない)とても古いESP32コア(1.x)ボードマネージャで2.xまたは3.xに更新する
Picoで曲が終わっても音が止まらないduty_u16(0)を呼んでいない各音のあとと最後にduty_u16(0)を呼ぶ
自分の曲を追加するには、まず楽譜から小節ごとにメロディーを書き出し、各小節の8分音符の合計を確認します。4/4拍子の小節なら8個分、3/4拍子なら6個分になるはずです。合計が合わなければ、音が抜けているか長さが間違っています。耳で探すよりずっと早く見つかります。

クリスマスソングを使ったプロジェクトのアイデア

  • サンタ検知器:暖炉の前でPIRセンサーが動きを検知したら、ジングルベルを鳴らします。作り方は「サンタ検知器」にあります。
  • 音楽付きクリスマスツリー:曲の演奏中、WS2812Bテープの色を音に合わせて変えます。ツリー本体については「クリスマスツリーのLED」を参照してください。
  • 真夜中のメロディー:「新年のカウントダウンタイマー」がゼロになったら、おめでとうクリスマスを鳴らします。
  • 玄関チャイム:12月の間は、チャイムのボタンを押したときに、いつものピンポンの代わりにひいらぎかざろうの最初のフレーズを鳴らします。
  • ボタンピアノ:8個のボタンでこれらの音を自分で演奏します。回路とコードは「Arduinoピアノ」にあります。季節のアイデアをもっと見たい場合は、「Arduinoのクリスマスプロジェクト」の一覧をご覧ください。

ブザーで初めてのメロディーを鳴らしたいなら、BlueGraysアプリの無料のブザープロジェクトがおすすめです。最初のビープ音から周波数の調整、国歌(トルコ国歌)のメロディーまで順に進められ、どのプロジェクトにも回路図、ステップごとの配線、すぐに動かせるコードが付いています。そこで身につけた習慣があれば、この記事の4曲のクリスマスソングを自分のオルゴールやクリスマスカードに簡単に追加できます。

よくある質問

ArduinoでJingle Bells(ジングルベル)を演奏するには?

パッシブブザーの+端子をD8に、もう一方をGNDにつなぎ、音の周波数を1つの配列に、長さを別の配列に書きます。ループで各音についてtone(8, 周波数, 時間)を呼び、delay(時間)で待ちます。サビは「ミ ミ ミ、ミ ミ ミ、ミ ソ ド レ ミ」で始まり、120 BPMでは8分音符が250 msです。

アクティブブザーでクリスマスソングを鳴らせますか?

いいえ。アクティブブザーは内部に周波数が固定された発振回路を持っていて、何を送っても同じ高さの音で鳴ります。メロディーには、パッシブブザー、圧電ディスク、またはトランジスタで駆動する小型スピーカーが必要です。

Arduinoのtone()関数の使い方は?

tone(pin, 周波数)はピンにデューティ比50%の矩形波を出力し、noTone(pin)が呼ばれるまで鳴り続けます。3番目の引数にミリ秒を渡すと、その時間が過ぎたところで自動的に音が止まります。Unoではtone()がTimer2を使うため、演奏中はD3とD11のPWMが動作しません。

ブザーの音を大きくするには?

最も効果的なのは、ピンから1 kΩの抵抗を通してNPNトランジスタを駆動し、トランジスタ経由で小型スピーカーに5 Vから電源を供給する方法です。トランジスタがない場合は、メロディーを1オクターブ上げるのも効果があります。圧電ブザーは2〜4 kHz付近で最も大きく鳴るからです。箱のような閉じた空間にブザーを入れても音が大きくなります。

曲の演奏中にArduinoはほかの処理ができますか?

delay()で書いたメロディーの演奏中は、Arduinoはほかに何もできません。各音の終わりをmillis()で確認すれば、loop()は待たずに戻るので、曲が続いている間もボタンの読み取り、LEDの点灯、センサーの測定が動き続けます。

Raspberry Pi Picoにtone()はありますか?

MicroPythonにはtone()はありませんが、machine.PWMで同じことができます。PWM(Pin(15))オブジェクトで、freq(周波数)で音を、duty_u16(32768)で50%のデューティ比を設定し、duty_u16(0)で音を止めます。音の周波数はArduinoとまったく同じです。

全プロジェクトを見る
ブザーの使い方
#13初級

ブザーの使い方

呼び鈴やアラームがどうやって音を出すのか、気になったことはありませんか?Arduinoが小さなブザーを短い間隔で鳴らし、音を出す、止める、を繰り返します。電気で音が生まれる仕組みを学び、メロディーを演奏するプロジェクトへの第一歩を踏み出せます。

4.7(89)
162
ブザーの周波数を調整
#14中級

ブザーの周波数を調整

4つのボタンでブザーの音を操作します。1つは音を鳴らし、1つは音を止め、残りの2つは音を高くしたり低くしたりします。音を高くするボタンや低くするボタンを押し続けると、音程が段階的に変化し、サイレンのように聞こえます。音の高低が生まれる理由を、自分の耳で確かめられます。

4.6(69)
119
ブザーでトルコ国歌を演奏
#15中級

ブザーでトルコ国歌を演奏

ボタンを押すと、小さなブザーがトルコ国歌を1音ずつ演奏し始めます。Arduinoが各音を正しい音程と長さで鳴らし、国歌の2節を最初から最後まで演奏した後、次のボタン操作を待ちます。シンプルな音響部品からメロディーが生まれる様子を、自分の耳で確かめられます。

4.8(107)
217
IR受信機・リモコン・ブザーでメロディーを再生
#18初級
プレミアム

IR受信機・リモコン・ブザーでメロディーを再生

テレビのリモコンのボタンでメロディーを奏でるオルゴールを作ります。赤外線受信機がリモコンの信号を受け取り、1つ目のボタンで軽快なゲーム音楽、2つ目でおなじみの童謡、3つ目で新年の歌をブザーから流します。リモコンが目に見えない光で通信する仕組みと、音符を音に変える方法を学びます。

4.8(57)
74
ブザーとボタンで作る簡単なピアノ
#26上級
プレミアム

ブザーとボタンで作る簡単なピアノ

8個のボタンで小さなピアノを作ります。各ボタンには、低い音から順にド、レ、ミ、ファ、ソ、ラ、シ、高いドが割り当てられています。ボタンを押している間はブザーから音が鳴り、離すと止まります。簡単な曲を弾きながら、音符の正体が音の振動であることを実感できます。

4.9(66)
88
ESP32とブザーでメロディーを演奏
#114初級
プレミアム

ESP32とブザーでメロディーを演奏

パッシブブザーで簡単なメロディー「きらきら星」を演奏します。Arduinoと同じようにtone()とnoTone()で音を鳴らします。ESP32 Arduino Core 3.0+でも同じ構文が使えます。パッシブブザーを使用してください。アクティブブザーではメロディーを演奏できません。

4.8(30)
55
Arduino 音で知らせる反応速度テスト:反射神経をミリ秒で測ろう(LCD+ブザー+LED 3個)
#97中級
プレミアム

Arduino 音で知らせる反応速度テスト:反射神経をミリ秒で測ろう(LCD+ブザー+LED 3個)

反射神経はどれくらい速いでしょうか。ボタンを押すと、赤LEDが位置について、黄LEDが用意を知らせ、1.5〜3.5秒のランダムな待ち時間が始まります。緑LEDが光ってブザーが鳴った瞬間にもう一度押すと、反応時間がI2C LCDにミリ秒で表示され、下の行にその回の最高記録と平均が出ます。緑より先に押すと画面にTOO EARLY!と表示され、残念な音が鳴ります。ボタンを長押しすると新しいプレイヤーになり、全員が同じ待ち時間の順番で勝負できます。

4.6(33)
50