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に移植します。

必要なのはアクティブブザー?それともパッシブブザー?
アクティブブザーは内部に発振回路を持っていて、5 Vを加えると常に同じ高さの音で鳴るため、メロディーは演奏できません。パッシブブザーは小さなスピーカーのようなもので、Arduinoのピンがオン・オフを繰り返す周波数で音を出します。見分ける簡単な方法は、ブザーを3〜5 Vの電池に一瞬当ててみることです。ピーと鳴り続ければアクティブ、カチッと1回だけ鳴ればパッシブです。アクティブ型は上面に白いシールが貼られていて底面がふさがっていることが多く、パッシブ型は裏側に緑色の基板が見えます。詳しくは「ブザーとは?」を参照してください。
| 特徴 | アクティブブザー | パッシブブザー |
|---|---|---|
| 内蔵の発振回路 | あり | なし |
| メロディーを演奏できる? | いいえ、1つの音だけ | はい、tone()でどの音も |
| 駆動に使う命令 | digitalWrite() | tone(pin, 周波数, 時間) |
| 電池に当てたとき | ピーと鳴り続ける | カチッと1回 |
| 最も大きく鳴る範囲 | 固定(通常2〜2.5 kHz) | 約2〜4 kHz(共振) |
配線:ブザー、2個のLED、ボタン
| 部品 | Arduino Uno | ESP32 | Raspberry Pi Pico |
|---|---|---|---|
| パッシブブザー + | D8 | GPIO 25 | GP15 |
| パッシブブザー − | GND | GND | GND |
| LED 1(220 Ωの抵抗付き) | D6 | GPIO 26 | GP14 |
| LED 2(220 Ωの抵抗付き) | D7 | GPIO 27 | GP13 |
| ボタン(もう一方の足はGND) | D2 | GPIO 4 | GP2 |
| タッチ用のアルミホイル | ― | GPIO 32(T9) | ― |
音の周波数:このクリスマスソングで使う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 | シ | 494 | NOTE_B4 |
| C5 | ド | 523 | NOTE_C5 |
| D5 | レ | 587 | NOTE_D5 |
| E5 | ミ | 659 | NOTE_E5 |
| F5 | ファ | 698 | NOTE_F5 |
| F#5 | ファ♯ | 740 | NOTE_FS5 |
| G5 | ソ | 784 | NOTE_G5 |
| A5 | ラ | 880 | NOTE_A5 |
| A#5 / Bb5 | シ♭ | 932 | NOTE_AS5 |
| B5 | シ | 988 | NOTE_B5 |
| C6 | ド | 1047 | NOTE_C6 |
| D6 | レ | 1175 | NOTE_D6 |
| E6 | ミ | 1319 | NOTE_E6 |
| F6 | ファ | 1397 | NOTE_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/4 | 120 BPM | 250 | 500 | 51 |
| おめでとうクリスマス | 3/4 | 150 BPM | 200 | 400 | 30 |
| きよしこの夜 | 3/4 | 75 BPM | 400 | 800 | 46 |
| ひいらぎかざろう | 4/4 | 約130 BPM | 230 | 460 | 68 |
最初のスケッチ:ジングルベルのサビ
- パッシブブザーの+端子をD8に、もう一方をGNDにつなぎます。
- Arduino IDEを開いて下のコードを貼り付け、ボードにArduino Unoを選択します。
- 書き込むと、ボードの起動と同時にサビが1回演奏されます。もう一度聴くにはリセットボタンを押します。
- 遅すぎたり速すぎたりする場合はEIGHTH_MSを変更します。200にすると速く、300にすると遅くなります。
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秒の無音のあと、次の曲が始まります。
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()の違い」を読んでください。
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のタッチピン」を参照してください。
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のセットアップから始めてください。
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)を呼ぶ |
クリスマスソングを使ったプロジェクトのアイデア
- サンタ検知器:暖炉の前で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とまったく同じです。
この記事を読んだ後に作れるプロジェクト
全プロジェクトを見る
ブザーの使い方
呼び鈴やアラームがどうやって音を出すのか、気になったことはありませんか?Arduinoが小さなブザーを短い間隔で鳴らし、音を出す、止める、を繰り返します。電気で音が生まれる仕組みを学び、メロディーを演奏するプロジェクトへの第一歩を踏み出せます。

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

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

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

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

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

Arduino 音で知らせる反応速度テスト:反射神経をミリ秒で測ろう(LCD+ブザー+LED 3個)
反射神経はどれくらい速いでしょうか。ボタンを押すと、赤LEDが位置について、黄LEDが用意を知らせ、1.5〜3.5秒のランダムな待ち時間が始まります。緑LEDが光ってブザーが鳴った瞬間にもう一度押すと、反応時間がI2C LCDにミリ秒で表示され、下の行にその回の最高記録と平均が出ます。緑より先に押すと画面にTOO EARLY!と表示され、残念な音が鳴ります。ボタンを長押しすると新しいプレイヤーになり、全員が同じ待ち時間の順番で勝負できます。
ほかの記事
BlueGraysアプリ
この回路をスマホでステップごとに作る
回路図、コード、部品リストを1つの画面で確認できます。Arduino、ESP32、Picoのプロジェクトを200件以上用意しています。

