Arduino Uno を用いた電子工作の基礎知識や開発フローをまとめます。
また、初心者向けの音楽ルーレットを作ります。
小中学生の自由研究や制作課題の参考になればと思います。
- エジソンアカデミー
国内最大級の子供向けロボットプログラミング教室であり、全国 45 都道府県に約 900 教室を展開しています。国際大会(URC)に出場することもできます。
- ヒューマンアカデミー
ロボット電話「RoBoHoN」や、世界初の対話できるロボット宇宙飛行士「KIROBO」(トヨタ自動車 & 電通と共同開発)の開発者である、話題のロボットクリエイター「高橋智隆」先生が監修した教材によるカリキュラムやイベントが用意されています。
Arduino の基本
Arduino とは
Arduino(アルデュイーノ)は、有名なマイコンボードの 1 つです。
マイコンボードとは、コンピュータシステムが集積された半導体チップであり、プリント基板上にマイクロコントローラチップと、そのチップの動作に必要な機能が搭載されています。
PC と比較すると、機能は最低限であり性能も低いですが、コンパクトで安価です。
マイクロコントローラは、家電や携帯電話、AV 機器、車など、多くの電子機器やマシンに組み込まれています。
マイコンボードの基本部品は、下記の通りです。
- CPU
- プログラムの格納用メモリ
- A/D コンバータ
- タイマー
- 外部機器と通信する入出力部
多くの Arduino には、Atmega 328 というマイクロコントローラチップが使用されています。
また、Arduino には、数十種類の型やシリーズがあります。
ここでは、最も初心者向きで有名な入門機である Arduino Uno を利用します。
Arduino Uno
下記は、Arduino Uno の概要図です。

主に利用する接続端子やピン、ボタンの概要は下表の通りです。
| 接続端子 / ピン / ボタン | 用途 | 番号 | 数 |
| DIGITAL(PWM~) | デジタル入出力 | 0 ~13 | 14 |
| アナログ出力(PWM) | 3 / 5 / 6 / 9 ~ 11 | 6 | |
| ANALOG IN | アナログ入力 | A0 ~ A5 | 5 |
| GND | 接地用端子 | GND | 出力用 : 1 電源用 : 2 |
| RESET (赤色ボタン) | プログラムの実行リセット | RESET | 1 |
| USB (銀色ボックス) | PC 接続用 USB 端子 (プログラム転送 / 電力供給) | – | 1 |
開発を行う上で、ひとまず押さえておくべき仕様は下記の通りです。
DIGITAL(PWM~)
デジタル入出力ピン
デジタル値(H / L レベルの信号)の入出力に使用します。
入出力のどちらのピンとして使用するかは、プログラムにおいて指定することができます。
スイッチにおける ON/OFF の読み取りや、LED の点灯や消灯を行う際に使用します。
アナログ出力ピン(PWM)
14 本のデジタル入出力ピンのうち 6 本は、PWM(Pulse Width Modulation)による擬似アナログ出力ピンとしても使用することができます。
PWM とは H レベルと L レベルの信号を交互に高速で出力することにより、平均の中間値における電圧を作り出す仕組みです。
プログラムの中で指定することで利用可能です。
LED の明るさやモーターの回転速度を制御する際に使用します。
ANALOG IN
アナログ値を入力する際に使用します。
各種センサからの入力電圧は、基盤上の A/Dコンバータにより 0 ~ 1023 の数値に変換されます。
A/D コンバータとは、電圧などのアナログ信号をデジタル信号に変換する機器です。
ボードへの電力供給
Arduino Uno は、AC アダプタ以外にも、PC の USB ポートから電源を取ることができます。
AC アダプタ用の端子に電源が接続されている場合は、その電源を利用し、そうでない場合は、USB からの電源を使用します。
その他、Arduino Uno の仕様は、公式ページにて確認することができます。
必要に応じて参照します。
開発方法
専用の統合開発環境である「Arduino IDE」を用いて開発します。
Windows または Mac の場合も同様に開発可能です。
開発フロー
大まかな開発フローは、下記の通りです。
Arduino IDE のテキストエディタにて、プログラムを作成します。
Arduino ボード上で動作するプログラムは、スケッチと呼ばれます。
ファイルの拡張子は、*.inoです。
C/C++ に似たシンプルな言語を用いて記述します。
スケッチには、setup 関数と loop 関数と 2 つの関数があり、それぞれを必ず利用します。
| 関数 | 概要 |
| setup | ・ボードにおける端子への入出力モードの割り当てや、初期化などの設定を定義
・スケッチの動作開始時に一度だけ実行 |
| loop | 繰り返し実行されるメインの処理を定義 |
通常のプログラミングと同様に、独自に関数を定義し、loop 関数内で呼び出すことができます。
そのため、全ての処理を loop 関数に記述する必要はありません。
また、センサや電圧の入出力などの操作は、開発環境に用意されている関数群を利用し、組み合わせることで定義します。
関数の詳細は、公式リファレンスにて確認することができます。
スケッチの作成後、IDE 上で検証(コンパイル)を行います。
コンパイルエラーがある場合、メッセージに従いスケッチを修正します。
Arduino IDE でコンパイルしたスケッチは、PC ではなく、Arduino ボード上で実行します。
そのため、USB で PC と接続し、ボードにアップロードする必要があります。
IDE 上のボタンをクリックして転送します。
ボードの電源を入れると、アップロードされたスケッチの実行が開始されます。
処理を停止させる場合は、電源をオフにします。
ただし、スイッチやセンサ等を用いたトリガによる処理の ON/OFF 操作や条件分岐は可能です。
以上が、Arduino IDE を持ちた開発フローです。
「スケッチの作成」と「回路の作成」と、どちらを先に完成させるか、あるいは平行して進めるかは任意です。
ここでは、説明の便宜上、前者を先に説明しました。
Arduino IDE のインストール
公式サイトからソフトウェアをダウンロードし、セットアップを行います。
投稿時点の最新バージョンは、1.8.19 です。
Windows 向けには、インストーラ版と、zip 版(実行可能ファイルと参照ファイルが同梱)とがありますが、ここでは前者を利用します。
- 「公式サイト」へアクセス
- Windows Win 7 and newer を選択
- JUST DOWNLOAD をクリック(自動ダウンロード開始)


- ダウンロードした arduino-1.8.19-windows.exe をダブルクリックして実行
- 利用規約の承諾(I Agree をクリック)
- Browse… からインストール先フォルダを設定(初期設定は C:\Program Files (x86)\Arduino)
- Install をクリック
- インストールの完了後に Close をクリック





- インストール先フォルダへ移動(初期設定の場合は C:\Program Files (x86)\Arduino)
- arduino.exe をダブルクリックで起動
- アイコンのオプションからタスクバーにピン留め(任意)
Arduino IDE のインストールとセットアップは以上です。
Mac 向けには、アプリケーションファイルが同梱された zip が用意されています。
- 「公式サイト」へアクセス
- Mac OS X 10.10 or newer を選択
- JUST DOWNLOAD をクリック(自動ダウンロード開始)


- ダウンロードした arduino-1.8.19-macosx.zip をダブルクリックして解凍
- 展開された Arduino.app をアプリケーションフォルダへ移動
- アプリケーションフォルダへ移動
- Arduino.app をダブルクリックで起動
- アイコンのオプションから Dock に追加(任意)
Arduino IDE のインストールとセットアップは以上です。
デモンストレーション
練習も兼ねて、簡単なスケッチと回路を作成します。
赤色 LDE を 1 秒間隔で点滅させる制御を実装します。
ここでは、Windows を用いますが、Mac の場合も同様です。
インストールした Arduino IDE を起動します。
起動すると、日付に基づく初期設定名が付いたスケッチが表示されます。
「ファイル」の「名前を付けて保存」から、編集するスケッチの名前を変更し、任意のフォルダに保存します。
Windows の場合、Ctrl + Shift + Sのキーバインドもあります。

ここでは、flash と名前を付けました。
このとき、同じ名前のフォルダが自動作成され、その中に flash.ino というファイルが保存されていることを確認できます。
下記コードを Arduino IDE に記述します。
#define LED 13 // 定数を定義し、13 番ピンを設定
void setup( ) {
pinMode( LED, OUTPUT ); // LED ピンの Pin Mode を出力に設定
}
void loop( ) {
digitalWrite( LED, HIGH ); // LED ピンに H レベルの電圧を入力
delay( 1000 ); // 処理を 1000 ミリ秒停止
digitalWrite( LED, LOW ); // LED ピンに L レベルの電圧を入力
delay( 1000 ); // 処理を 1000 ミリ秒停止
}
pinMode、digitalWrite、delay は、Arduino で事前に定義されている関数です。
引数や戻り値などの関数の仕様は、前述の「公式リファレンス」にて確認できます。
また、INPUT と OUTPUT も、Arduino で定義されている定数です。
C 言語と同様に、#define を用いることで、独自の定数を宣言できます。
Arduino IDE 上で検証(コンパイル)を行います。
画面左上のチェックマークをクリックすることで開始します。



検証結果は、画面下のウィンドウに表示されます。
エラーがある場合はスケッチの修正を行い、コンパイルが無事完了した場合は、ボードへアップロードすることができます。
下記の実態配線図に従い、スケッチに対応する回路を作成します。
赤色 LED のアノード(A: 正極)側を、Arduino Uno の 13 番ピンに、カソード(K: 負極)側を GND に接続します。
一般的に、端子の長い方がアノードで、短い方がカソードです。
LED の接続の際は、抵抗(330 Ω 程度)を使用します。

コンパイル済のスケッチを Arduino ボードにアップロードします。
PC とボードを USB で接続し、右矢印のボタンをクリックします。

ここでは、Arduino Uno の電源は、USB 接続している PC から供給されます。
そのため、スケッチのアップロード直後に実行が開始されます。
赤色 LED が 1 秒間隔で点滅することを確認できれば、スケッチおよび回路が正しく実装できています。
以上が、簡単な制御を例題とした Arduino Uno による開発のデモンストレーションになります。
音楽ルーレットの制作
制作する音楽ルーレットの仕様と、必要なスケッチおよび回路をまとめます。
仕様
タクトスイッチを押してスタートさせ、当選すると、効果音または BGM が流れます。
赤色 LED の点滅でルーレットを表現し、回転に合わせて音が出ます。
音は圧電スピーカーから出力させます。
ポテンショメータ(可変抵抗)を調整することにより、ルーレットの当選内容を 5 段階に変更可能で、グレードはフルカラー LED の色を見て確認することができます。
消灯、青色、緑色、赤色、白色 の順に当選確率が上昇し、当選内容もグレードアップさせ、異なる効果音または曲が流れるようになります。
効果音を 6 つと、BGM を 2 つ制作しました。
用途と関数名は下表の通りです。
| 効果音 / BGM | 概要 | 関数名 |
| ハズレ | ハズレの効果音 | miss |
| ポテト | ポテトが揚がった時の効果音 | mc |
| スウィープ | ロックギターのような派手な効果音 | sweep |
| コインゲット | コインをゲットした時の効果音 |
coinGet
|
| ライフアップ | ライフアップをイメージした効果音 |
lifeUp
|
| コインゲットラッシュ | 「ライフアップ」の中で利用する効果音 |
coinGetRush
|
| アンダーグラウンド | マリオが地下に潜った時の BGM |
underWorld
|
| パイレーツ | パイレーツオブカリビアン風の BGM |
pirates
|
「ライフアップ」は「コインゲット」の当選を 6 回繰り返した際に流れる「隠し BGM」です。
効果音や BGM のリズムに合わせ、ルーレットを鮮やかに点滅させる点灯パターンも実装しました。
スケッチ
制御フローの概要は、下記の通りです。
- 乱数の種を変更
- ポテンショメータ(可変抵抗)の値を取得し、フルカラー LED の光を変更
- タクトスイッチが押されたか?(YES : 4 へ / NO : 1 へ)
- 乱数を取得し、当選ピンを決定
- ルーレットの演出実行と当選発表
- 当選結果に基づく演出実行
上記のプロセスを実装します。
下記ファイルに分割して作成しました。
| ファイル | 概要 |
| musicRoulette.ino | ・メインスケッチ
・setup 関数と loop 関数を定義した制御フローの骨格 |
| mrlib.ino | ・サブスケッチ
・制御に必要な各種関数を独自定義 |
| mrlib.h | ・ヘッダファイル(メインスケッチでインクルード)
・定数や変数の定義とプロトタイプ宣言 |
また、loop 関数にて制御フローを記述し、利用する関数はサブスケッチから呼び出します。
/*
制御に必要な各種関数を独自定義したヘッダファイルをインクルード
*/
#include "mrlib.h"
/*
setup 関数
*/
void setup() {
// 圧電スピーカーピンの Pin Mode を出力に設定
pinMode( SPEAKER, OUTPUT );
// フルカラー LED における各ピンの Pin Mode を出力に設定
pinMode( LED_R, OUTPUT );
pinMode( LED_G, OUTPUT );
pinMode( LED_B, OUTPUT );
// ルーレットを構成する赤色 LED における各ピン(2 ~ 7番)の Pin Mode を出力に設定
for( int i = 2; i <= 7; i++ ) {
pinMode( i, OUTPUT );
}
}
/*
loop 関数
*/
void loop() {
// 未接続のアナログ入力ピンのノイズを利用して乱数を初期化
randomSeed( analogRead( 0 ) );
int grade; // ポテンショメータの値
// タクトスイッチが OFF の場合は待機(プルアップ回路)
while ( digitalRead( 13 ) == HIGH ){
grade = analogRead( 1 ); // ポテンショメータの値を取得
showGrade( grade ); // フルカラー LED の発光色を調整
}
showGradeOff(); // 消灯
digitalWrite( hit, LOW ); // 当選 LED を消灯
grade = analogRead( 1 ); // ポテンショメータを取得
int resultOfRand = random( 0, 5 + 1 ); // random( min, max ) の戻り値は min to max-1
hit = resultOfRand + 2; // ピン番号に調整(赤色 LED のピン番号は 2 ~ 7)
// ポテンショメータの値と当選ピンに基づく演出実行
play( grade, hit );
}
ヘッダファイルである mrlib.h にて、各種ピンへ定数の割り当てや変数の定義、関数のプロトタイプ宣言を行います。
また、サブスケッチである mrlib.ino にて、各機能の処理を記述した関数群を定義します。
mrlib.h
/* 音符の定義 */
#define NOTE_D3 147
#define NOTE_DS3 156
#define NOTE_E3 165
#define NOTE_F3 175
#define NOTE_G3 196
#define NOTE_GS3 208
#define NOTE_A3 220
#define NOTE_AS3 233
#define NOTE_B3 247
#define NOTE_C4 262 // 鍵盤の真ん中のドを基準に C4 と表記
#define NOTE_CS4 277
#define NOTE_D4 294
#define NOTE_DS4 311
#define NOTE_E4 330
#define NOTE_F4 349
#define NOTE_FS4 370
#define NOTE_G4 392
#define NOTE_GS4 415
#define NOTE_A4 440
#define NOTE_AS4 466
#define NOTE_B4 494
#define NOTE_C5 523
#define NOTE_D5 587
#define NOTE_E5 659
#define NOTE_F5 698
#define NOTE_G5 784
#define NOTE_A5 880
#define NOTE_B5 988
/* フルカラー LED のピンへの割り当て */
#define LED_R 10
#define LED_G 9
#define LED_B 8
/* 圧電スピーカーのピンへの割り当て */
#define SPEAKER 12
/* 当選 LED ピンの番号 */
int hit;
/* コインの総獲得枚数 */
int totalCoin = 1;
/* ポテンショメータの値と当選ピンに基づく演出実行 */
void play( int grade, int hit );
/* ルーレットの演出(点滅と音の出力)*/
void roulette();
/* 当選発表 */
void announceHit( int hit );
/* 当選セット */
void hitSet_bad(); // 最低グレード
void hitSet_standard(); // 標準グレード
void hitSet_middle(); // 中級グレード
void hitSet_super(); // 上級グレード
void hitSet_ultra(); // 最上級グレード
/* 効果音 */
void miss(); // ハズレ
void potato(); // ポテト
void sweep(); // スウィープ
void coinGet(); // コインゲット
void lifeUp() ; // ライフアップ
void flash( int num ); // 赤色 LED の点滅(効果音に合わせて利用)
/* BGM */
void pirates(); // パイレーツ
void flashPirates( int &num ); // パイレーツの BGM に合わせた赤 LED の点滅
void underWorld(); // アンダーワールド
void buzz( long frequency, long length ); // 音符の出力(アンダーワールドにて利用)
/* フルカラー LED の操作 */
void showGrade( int grade ); // 色を調整
void showGradeOff(); // 消灯
/* 全赤色 LED を消灯 */
void flashOff();
mrlib.ino
/*
ポテンショメータの値と当選ピンに基づく演出実行
*/
void play( int grade, int hit ) {
roulette();
announceHit( hit );
if ( grade >= 1000 ) hitSet_ultra();
else if ( grade >= 800 ) hitSet_super();
else if ( grade >= 500 ) hitSet_middle();
else if ( grade >= 200 ) hitSet_standard();
else hitSet_bad();
}
/*
ルーレットの演出(点滅と音の出力)
*/
// void tone( pin, frequency ) : pin へ frequency(Hz)に指定した周波数で電圧を印加
void roulette() {
for ( int i = 0; i < 3; i++ ) { // 3 周
for ( int j = 2; j <= 7; j++ ) {
tone( SPEAKER, 800 );
digitalWrite( j , HIGH );
delay( 40 );
noTone( SPEAKER ); // 印加を停止
digitalWrite( j , LOW );
delay( 40 );
}
}
}
/*
当選発表
*/
void announceHit( int hit ) {
// 当選ピン番号
unsigned int i;
// 当選ピンまでスローで点滅しながら移動(音声付き)
for ( i = 2; i < hit; i++ ) {
tone( SPEAKER, 700 );
digitalWrite( i , HIGH );
delay( 350 );
noTone( SPEAKER );
digitalWrite( i , LOW );
delay( 350 );
}
// 当選ピンで 2 回点滅(音声付き)
tone( SPEAKER, 900 );
digitalWrite( hit, HIGH );
delay( 100 );
noTone( SPEAKER );
digitalWrite( hit, LOW );
delay( 100 );
tone( SPEAKER, 900 );
digitalWrite( i, HIGH );
delay( 100 );
noTone( SPEAKER );
digitalWrite( i, LOW );
delay( 100 );
digitalWrite( i, HIGH );
delay( 100 );
}
/*
最低グレードの当選セット
*/
void hitSet_bad() {
if( hit == 2 || hit == 4 || hit == 5 || hit == 6 || hit == 7 ) miss();
if( hit == 3 ) coinGet();
}
/*
標準グレードの当選セット
*/
void hitSet_standard() {
if( hit == 3 || hit == 5 ) miss();
if( hit == 2 || hit == 4 ) coinGet();
if( hit == 6 ) sweep();
if( hit == 7 ) potato();
}
/*
中級グレードの当選セット
*/
void hitSet_middle() {
if( hit == 4 || hit == 6 ) miss();
if( hit == 2 ) coinGet();
if( hit == 5 ) sweep();
if( hit == 3 || hit == 7 ) potato();
}
/*
上級グレードの当選セット
*/
void hitSet_super() {
if( hit == 5 ) miss();
if( hit == 6 ) coinGet();
if( hit == 7 ) sweep();
if( hit == 2 ) lifeUp();
if( hit == 3 ) underWorld();
if( hit == 4 ) pirates();
}
/*
最上級グレードの当選セット
*/
void hitSet_ultra() {
if( hit == 2 || hit == 4 || hit == 6 ) underWorld();
if( hit == 3 || hit == 5 || hit == 7 ) pirates();
}
/*
ハズレの効果音
*/
void miss() {
tone( SPEAKER, 300, 50 );
delay( 200 );
tone( SPEAKER, 300, 500 );
}
/*
ポテトの効果音
*/
void potato() {
int count = 0;
for ( int i = 0; i < 5; i++ ) {
tone( SPEAKER, 785 );
flash( count++ );
delay( 180 );
noTone( SPEAKER );
flashOff();
delay( 60 );
tone( SPEAKER, 698 );
flash( count++ );
delay( 180 );
noTone( SPEAKER );
delay( 60 );
tone( SPEAKER, 784 );
flash( count++ );
delay( 180 );
noTone( SPEAKER );
flashOff();
delay( 60 );
delay( 190 );
}
}
/*
スウィープの効果音
*/
void sweep() {
for ( int i = 0; i < 3; i++ ) {
int count = 2;
for ( int j = 300; j <= 800; j += 100 ) {
tone( SPEAKER, j );
digitalWrite( count++, HIGH );
delay( 50 );
noTone( SPEAKER );
}
flashOff();
delay( 5 );
for ( int k = 800; k >= 300; k -= 100 ) {
tone( SPEAKER, k );
digitalWrite( --count, HIGH );
delay( 50 );
noTone( SPEAKER );
digitalWrite( count, LOW );
}
}
}
/*
コインゲットの効果音
*/
void coinGet() {
digitalWrite( hit, LOW );
for ( int got = 2; got <= totalCoin + 1; got++ ) digitalWrite( got, HIGH );
for ( int i = 0; i < 250; i++ ) {
digitalWrite( SPEAKER, HIGH ) ;
delayMicroseconds( 253 );
digitalWrite( SPEAKER, LOW );
delayMicroseconds( 253 );
}
for ( int j = 0; j < 800; j++ ) {
digitalWrite( SPEAKER, HIGH );
delayMicroseconds( 189 );
digitalWrite( SPEAKER, LOW );
delayMicroseconds( 189 );
}
digitalWrite( totalCoin + 1 , HIGH );
totalCoin++;
if ( totalCoin == 7 ) {
coinGetRush( 6 );
lifeUp();
totalCoin = 1;
}
delay( 1000 );
flashOff();
}
/*
コインゲットラッシュの効果音
*/
void coinGetRush( int n ) {
flashOff();
int count = 2;
for ( int i = 0; i < n - 1; i++ ) {
for ( int j = 0; j < 250; j++ ) {
digitalWrite( SPEAKER, HIGH );
delayMicroseconds( 253 );
digitalWrite( SPEAKER, LOW );
delayMicroseconds( 253 );
}
digitalWrite( count++, HIGH );
delay( 5 );
}
for ( int i = 0; i < 250; i++ ) {
digitalWrite( SPEAKER, HIGH ) ;
delayMicroseconds( 253 );
digitalWrite( SPEAKER, LOW );
delayMicroseconds( 253 );
}
digitalWrite( count, HIGH );
for ( int j = 0; j < 800; j++ ) {
digitalWrite( SPEAKER, HIGH );
delayMicroseconds( 189 );
digitalWrite( SPEAKER, LOW );
delayMicroseconds( 189 );
}
delay( 800 );
flashOff();
}
/*
ライフアップの効果音
*/
void lifeUp() {
digitalWrite( 6, HIGH );
for ( int i = 0; i < 97; i++ ) {
digitalWrite( SPEAKER, HIGH );
delayMicroseconds( 379 );
digitalWrite( SPEAKER, LOW );
delayMicroseconds( 379 );
}
digitalWrite( 2, HIGH );
for ( int j = 0; j < 235; j++ ) {
digitalWrite( SPEAKER, HIGH );
delayMicroseconds( 319 );
digitalWrite( SPEAKER, LOW );
delayMicroseconds( 319 );
}
digitalWrite( 4, HIGH );
for ( int k = 0; k < 396; k++ ) {
digitalWrite( SPEAKER, HIGH );
delayMicroseconds( 189 );
digitalWrite( SPEAKER, LOW );
delayMicroseconds( 189 );
}
digitalWrite( 7, HIGH );
for ( int l = 0; l < 315; l++ ) {
digitalWrite( SPEAKER, HIGH );
delayMicroseconds( 238 ) ;
digitalWrite( SPEAKER, LOW );
delayMicroseconds( 238 );
}
digitalWrite( 3, HIGH );
for ( int m = 0; m < 353; m++ ) {
digitalWrite( SPEAKER, HIGH );
delayMicroseconds( 212 );
digitalWrite( SPEAKER, LOW );
delayMicroseconds( 212 );
}
digitalWrite( 5, HIGH );
for ( int n = 0; n < 471; n++ ) {
digitalWrite( SPEAKER, HIGH );
delayMicroseconds( 159 );
digitalWrite( SPEAKER, LOW );
delayMicroseconds( 159 );
}
delay( 800 );
flashOff();
}
/*
赤色 LED の点滅(効果音に合わせて利用)
*/
void flash( int num ) {
if ( num % 2 == 0 ) {
digitalWrite( 2, HIGH );
digitalWrite( 4, HIGH );
digitalWrite( 6, HIGH );
} else {
digitalWrite( 3, HIGH );
digitalWrite( 5, HIGH );
digitalWrite( 7, HIGH );
}
}
/*
パイレーツの BGM
*/
void pirates() {
// 曲のスピード(仕様上、数値とスピードは反比例)
// songspeed = 2.0 とすると遅くなるが同じ音が 2 回以上続くときノイズが入る
const int songSpeed = 1.5;
// 音符の配列を作成(0 は休符)
const int notes[] = {
NOTE_E4, NOTE_G4, NOTE_A4, NOTE_A4, 0, // ミ ソ ラ ラ 休符
NOTE_A4, NOTE_B4, NOTE_C5, NOTE_C5, 0, // ラ シ ド ド 休符
NOTE_C5, NOTE_D5, NOTE_B4, NOTE_B4, 0, // ド レ シ シ 休符
NOTE_A4, NOTE_G4, NOTE_A4, 0, // ラ ソ ラ 休符
// 別パート
NOTE_A4, NOTE_A4,
NOTE_A4, NOTE_B4, NOTE_C5, NOTE_C5, 0,
NOTE_C5, NOTE_D5, NOTE_B4, NOTE_B4, 0,
NOTE_A4, NOTE_G4, NOTE_A4, 0,
NOTE_E4, NOTE_G4, NOTE_A4, NOTE_A4, 0,
NOTE_A4, NOTE_C5, NOTE_D5, NOTE_D5, 0,
NOTE_D5, NOTE_E5, NOTE_F5, NOTE_F5, 0,
NOTE_E5, NOTE_D5, NOTE_E5, NOTE_A4, 0,
NOTE_A4, NOTE_B4, NOTE_C5, NOTE_C5, 0,
NOTE_D5, NOTE_E5, NOTE_A4, 0,
NOTE_A4, NOTE_C5, NOTE_B4, NOTE_B4, 0,
NOTE_C5, NOTE_A4, NOTE_B4, 0,
// クライマックス
NOTE_E5, 0, 0, NOTE_F5, 0, 0,
NOTE_E5, NOTE_E5, 0, NOTE_G5, 0, NOTE_E5, NOTE_D5, 0, 0,
NOTE_D5, 0, 0, NOTE_C5, 0, 0,
NOTE_B4, NOTE_C5, 0, NOTE_B4, 0, NOTE_A4,
NOTE_E5, 0, 0, NOTE_F5, 0, 0,
NOTE_E5, NOTE_E5, 0, NOTE_G5, 0, NOTE_E5, NOTE_D5, 0, 0,
NOTE_D5, 0, 0, NOTE_C5, 0, 0,
NOTE_B4, NOTE_C5, 0, NOTE_B4, 0, NOTE_A4
};
// 音の長さを定義
// 4分音符 = 500 ms | 8分音符 = 250 ms | 16分音符 = 125 ms
int duration[] = {
125, 125, 250, 125, 125,
125, 125, 250, 125, 125,
125, 125, 250, 125, 125,
125, 125, 375, 125,
250, 125,
// 別パート
125, 125, 250, 125, 125,
125, 125, 250, 125, 125,
125, 125, 375, 125,
125, 125, 250, 125, 125,
125, 125, 250, 125, 125,
125, 125, 250, 125, 125,
125, 125, 125, 250, 125,
125, 125, 250, 125, 125,
250, 125, 250, 125,
125, 125, 250, 125, 125,
125, 125, 375, 375,
// クライマックス
250, 125, 375, 250, 125, 375,
125, 125, 125, 125, 125, 125, 125, 125, 375,
250, 125, 375, 250, 125, 375,
125, 125, 125, 125, 125, 500,
250, 125, 375, 250, 125, 375,
125, 125, 125, 125, 125, 125, 125, 125, 375,
250, 125, 375, 250, 125, 375,
125, 125, 125, 125, 125, 125
};
int count = 0;
int size = sizeof( notes ) / sizeof( int ); // size は音符の総数
// それぞれの音符について処理
for ( int i = 0; i < size; i++ ) {
// 休符は無視
if ( notes[ i ] != 0 ) flashPirates( count );
int rest = duration[ i ] * songSpeed; // 楽曲スピードの調整可能
tone( SPEAKER, notes[ i ], rest ); // tone( pin, frequency, duration );
delay( rest );
}
delay( 100 );
flashOff();
}
/*
パイレーツの BGM に合わせた赤 LED の点滅
*/
void flashPirates( int &num ) {
if ( num == 0 ) {
digitalWrite( 2, HIGH );
digitalWrite( 3, LOW );
digitalWrite( 4, HIGH );
digitalWrite( 5, LOW );
digitalWrite( 6, HIGH );
digitalWrite( 7, LOW );
num++;
} else if ( num == 1 ) {
digitalWrite( 2, LOW );
digitalWrite( 3, HIGH );
digitalWrite( 4, LOW );
digitalWrite( 5, HIGH );
digitalWrite( 6, LOW );
digitalWrite( 7, HIGH );
num++;
} else {
digitalWrite( 2, HIGH );
digitalWrite( 3, HIGH );
digitalWrite( 4, HIGH );
digitalWrite( 5, HIGH );
digitalWrite( 6, HIGH );
digitalWrite( 7, HIGH );
num = 0;
}
}
/*
アンダーワールドの BGM
*/
void underWorld() {
// 音符の配列を作成(0 は休符)
const int notes[] = {
NOTE_C4, NOTE_C5, NOTE_A3, NOTE_A4,
NOTE_AS3, NOTE_AS4, 0,
0,
NOTE_C4, NOTE_C5, NOTE_A3, NOTE_A4,
NOTE_AS3, NOTE_AS4, 0,
0,
NOTE_F3, NOTE_F4, NOTE_D3, NOTE_D4,
NOTE_DS3, NOTE_DS4, 0,
0,
NOTE_F3, NOTE_F4, NOTE_D3, NOTE_D4,
NOTE_DS3, NOTE_DS4, 0,
0,
NOTE_DS4, NOTE_CS4, NOTE_D4,
NOTE_CS4, NOTE_DS4,
NOTE_DS4, NOTE_GS3,
NOTE_G3, NOTE_CS4,
NOTE_C4, NOTE_FS4, NOTE_F4, NOTE_E3, NOTE_AS4, NOTE_A4,
NOTE_GS4, NOTE_DS4, NOTE_B3,
NOTE_AS3, NOTE_A3, NOTE_GS3,
0, 0, 0
};
// 音の長さを定義
// 音符の全音符を 1000 ms として分音符を作成
const int duration[] = {
12, 12, 12, 12,
12, 12, 6,
3,
12, 12, 12, 12,
12, 12, 6,
3,
12, 12, 12, 12,
12, 12, 6,
3,
12, 12, 12, 12,
12, 12, 6,
6, 18, 18, 18,
6, 6,
6, 6,
6, 6,
18, 18, 18, 18, 18, 18,
10, 10, 10,
10, 10, 10,
3, 3, 3
};
const int noteLength = 56;
for ( int i = 0; i < noteLength; i++ ) {
int noteDuration = 1000 / duration[ i ]; // x 分音符を作成
buzz( notes[ i ], noteDuration ); // 音符の出力
int pause = noteDuration * 1.3; // 音符を明確に区別するために最小時間で 1.3 が最適
delay( pause );
buzz( 0, noteDuration );
}
}
/*
音符の出力(アンダーワールドにて利用)
*/
void buzz( long frequency, long length ) {
// digitalWrite 間の delay を計算(実質的には音の高さを計算)
// 1000000 s → μs に変換 (HIGH/LOW の 2 つのサイクルがあるため 2 で割る)
long delayValue = 1000000 / frequency / 2;
// 波の数を計算(音の長さを計算)
long cycles = frequency * length / 1000; // length / 1000 : ms → s の変換
flash( frequency ); // 音の高さが偶数、奇数の場合で点灯が場合分け
for ( long i = 0; i < cycles; i++ ) {
digitalWrite( SPEAKER, HIGH );
delayMicroseconds( delayValue );
digitalWrite( SPEAKER, LOW );
delayMicroseconds( delayValue );
}
flashOff();
}
/*
フルカラー LED の色を変更
*/
void showGrade( int grade ) {
if ( grade >= 1000 ) {
digitalWrite( LED_R, HIGH );
digitalWrite( LED_G, HIGH );
digitalWrite( LED_B, HIGH );
}
else if ( grade >= 800 ) {
digitalWrite( LED_R, HIGH );
digitalWrite( LED_G, LOW );
digitalWrite( LED_B, LOW );
}
else if ( grade >= 500 ) {
digitalWrite( LED_R, LOW );
digitalWrite( LED_G, HIGH );
digitalWrite( LED_B, LOW );
}
else if ( grade >= 200 ) {
digitalWrite( LED_R, LOW );
digitalWrite( LED_G, LOW );
digitalWrite( LED_B, HIGH );
}
else {
digitalWrite( LED_R, LOW );
digitalWrite( LED_G, LOW );
digitalWrite( LED_B, LOW );
}
}
/*
フルカラー LED の消灯
*/
void showGradeOff() {
digitalWrite( LED_R, LOW );
digitalWrite( LED_G, LOW );
digitalWrite( LED_B, LOW );
}
/*
全赤色 LED を消灯
*/
void flashOff() {
digitalWrite( 2, LOW );
digitalWrite( 3, LOW );
digitalWrite( 4, LOW );
digitalWrite( 5, LOW );
digitalWrite( 6, LOW );
digitalWrite( 7, LOW );
}
効果音や BGM の音楽は、圧電スピーカーを制御する tone 関数を利用し、音階を再現することで実装します。
特に、曲を制作する際は、音符を音の高さとリズムの 2 つに分け、それぞれの順序を対応付けて配列に格納し、両者を掛け合わせることで再現します。
Arduino を用いた音楽制作の詳細については、下記を参照ください。
回路
実態配線図は、下記の通りです。
この図を参照しながら、回路を作成します。

配線手順と各パーツの詳細は下記の通りです。
タクトスイッチを13 番ピンに接続します。
このとき、10 KΩ 程度の大きな抵抗を挟みます。
これにより、スイッチが押されるまで、常に H レベルの値が出力され、ボタンが押された時、L レベルの出力が行われます。
こうしたプルアップ回路により、スケッチ上の条件分岐に利用します。
ボタンが押されるまでループよる待機状態を作り出し、ボタンが押されたことをトリガーに以降のプログラムを実行するように実装します。
ポテンショメータは、回転角によって抵抗値が変わるパーツです。
右に回すことで抵抗値が上がり、この値をスケッチにおける閾値として用います。
3 つの端子の内、右端に +5V、左端に GND、真中に A1 のアナログ入力ピンを接続します。
フルカラー LED は、「赤」「緑」「青」の 3 色の LED が 1 つにまとめられたものです。
各 LED の明るさを変化させ、光を混合することにより、様々な色の光を作り出すことができます。
色ごとに LED の特性が異なるため、それぞれに適した抵抗を選択する必要があります。
| LED | 目安 | 当回路 | ピン番号 |
| 赤 | 300 Ω 程度 | 330 Ω | 10 |
| 緑 | 270 Ω 程度 | 270 Ω | 9 |
| 青 | 600 Ω 程度 | 560 Ω | 8 |
左側の端子から、赤、GND、緑、青、の順になるように設置し、適当な抵抗を接続します。
赤色 LED は、正六角形に並べて設置し、それぞれに 330 Ω の抵抗を接続します。
右下の赤色 LED から時計回りに 2 ~ 7 番ピン へ接続します。
ルーレットは、2 番ピン からスタートします。
圧電スピーカーは、薄板の圧電振動板を金属板に貼り付けて作製される一種のブザーです。
H/L レベルの電圧を高速で繰り返し印加することで圧電振動板が伸縮し、内部の金属板が振動します。
これにより、音波を発生させることができ、電圧の間隔(周波数)を制御することで音階を作り出すことができます。
Arduino 上で制御する場合、H/L レベルの電圧のみを印加するため、デジタル出力ピンに接続します。
ここでは、スピーカの正極を 12 番ピン に接続します。
回路の配線は以上です。
おすすめの開発アイテム
電子工作の初心者に最適な開発キットや、参考書を紹介します。
小中学生向けの電子工作講座にて、利用しています。
ELEGOO Arduino UNO R3 スターターキット
初心者向けの入門用の開発セットです。
マイコンボードやブレッドボードをはじめ、開発に必要十分な電子部品が全て揃えられています。
単体購入すると高くなる付属パーツも豊富に同梱されており、コスパが良いです。
マイコンボードは、ELEGOO 社の互換機ではありますが、全く問題なく動作します。
さらに電子部品を追加したバージョンの開発セットもあります。
初心者では使いきれない可能性もありますが、買い揃えるのにハードルが高いアイテムに出会うことができます。
これ1冊でできる!Arduino ではじめる電子工作 超入門 改訂第4版
Arduino を用いた電子工作の書籍では、最も有名な 1 冊です。
マイコンボードや部品の扱い方、スケッチを用いた電子回路の制御方法などの基礎知識が丁寧に解説されており、初心者の方でも安心して学習することができます。
中級者向けにも、細かなノウハウや応用テクニックも豊富に紹介されています。
また、作品例を通じて、実際に手を動かしながら理解を深めることができます。
サンプルのスケッチや回路を改変しながら、独自の作品としてカスタマイズすることでも、十分に楽しむことができます。
手元に置いておくと、開発がスムーズに進みます。
学生時代の開発にて、旧版を活用していましたが、とても重宝しました。
1週間で C 言語の基礎が学べる本
Arduino は、C言語とほぼ同じ文法で記述します。
スケッチを作成するうえで、プログラミングの知識不足を感じる場合は、C言語の習得も兼ねて体系的に学習しておくと、スムーズに開発を行うことができます。
この書籍は、「1週間シリーズ」の C言語編です。
必要なポイントを押さえ、短期間で基礎知識を学び、全体像を把握することができます。
プログラミングを始めたばかりの超初心者が対象です。
初歩的な文法をはじめ、基本的なアルゴリズムとデータ構造を学び、練習問題を通じて手を動かすことで理解を深めることができます。
- エジソンアカデミー
国内最大級の子供向けロボットプログラミング教室であり、全国 45 都道府県に約 900 教室を展開しています。国際大会(URC)に出場することもできます。
- ヒューマンアカデミー
ロボット電話「RoBoHoN」や、世界初の対話できるロボット宇宙飛行士「KIROBO」(トヨタ自動車 & 電通と共同開発)の開発者である、話題のロボットクリエイター「高橋智隆」先生が監修した教材によるカリキュラムやイベントが用意されています。
CHAM 





