工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Manufacturing Technology >> 製造プロセス

ジョルノのテーマ(Il Vento Doro)をデュアルArduinoで演奏 – 精密なピッチとタイミング

部品と材料

部品数量備考
Arduino UNO2メインボードとセカンダリボード用
MOSFETトランジスタ(スイッチング用)2スピーカー駆動用
スピーカー:3W、4Ω4各ボードに2個ずつ(ステレオまたはレイヤー用)
抵抗 1kΩ(0.25W)2ゲート抵抗など
ブレッドボード用電源スティック 5V/3.3V(SparkFun)1外部電源供給用
ジャンパーワイヤー(汎用)1セット配線用

必要な工具と機器

使用ソフトウェアとオンラインサービス

プロジェクト概要

このプロジェクトでは、ジョジョの奇妙な冒険 第5部の主題歌「ジョルノのテーマ(Il Vento Doro)」を2台のArduino UNOを使って再現します。内蔵のtone()関数とシンプルなデジタル・ハンドシェイクを活用し、両ボードを同期させて重なる音符をリアルタイムで演奏します。

プライマリ(主)ボードはピン2からトリガー・パルスを出力し、セカンダリ(副)ボードはピン3でそれを受信します。各ボードは専用の波形配列を実行し、高いオクターブの音符をセカンダリ側で担当させることで、単一ボードでは発生しがちな周波数クリッピング(音割れ)を回避しています。

注意: スケッチ内で #include "Color.h" として読み込まれているヘッダーファイルには、Pink1, Blue1, Orange2 などの音符定数(周波数値)が定義されている必要があります。このファイルが別途用意されていないとコンパイルエラーになります。一般的な pitches.h などを流用するか、独自に定義してください。

コード

パート1:プライマリArduino(マスター)

#include "Color.h"

int S[] = {
  Pink1, 0, Pink1, 0, Pink1, Blue1, 0, Pink1, 0, Orange2, 0, Pink1, 0, Green1, Blue1, 0,
  Pink1, 0, Pink1, 0, Pink1, Blue1, 0, Pink1, 0, LGreen2, 0, Yellow2, 0, Orange2, Blue1, 0,
  Pink1, 0, Pink1, 0, Pink1, Blue1, 0, Pink1, 0, Orange2, 0, Pink1, 0, Green1, Blue1, 0,
  Pink1, 0, Pink1, 0, Pink1, Blue1, Pink1, Orange2, 0, LGreen2, 0, Yellow2, 0, Orange2, Blue1, 0,
  Pink1, 0, Pink1, 0, Pink1, Blue1, 0, Pink1, 0, Orange2, 0, Pink1, 0, Green1, Blue1, 0,
  Pink1, 0, Pink1, 0, Pink1, Blue1, 0, Pink1, 0, LGreen2, 0, Yellow2, 0, Orange2, Blue1, 0,
  Pink1, 0, Pink1, 0, Pink1, Blue1, 0, Pink1, 0, Orange2, 0, Pink1, 0, Green1, Blue1, 0,
  Pink1, 0, Pink1, 0, Pink1, 0, Blue1, Pink1, 0, 0, 0, 0, Pink1, 0, Orange2, 0, Yellow2,
  LGreen2, 0, Green2, 0, Blue2, 0, Green2, 0, Blue2, Purple2, 0, Pink2, 0, Purple2, 0,
  Blue2, Green2, 0, Yellow2, 0, Orange2, LBlue1, 0, Blue1, 0, Purple1, 0, Pink1, 0, Orange2, 0,
  Yellow2, LGreen2, 0, Green2, 0, Blue2, 0, Green2, 0, Blue2, Purple2, 0, Pink2, 0, Blue2,
  Pink2, Blue2, 0, Purple2, Pink2, 0, LBlue1, 0, LBlue1, Blue1, Blue1, Purple1, 0, Pink1, 0,
  Orange2, 0, Yellow2, LGreen2, 0, Green2, 0, Blue2, 0, Green2, 0, Blue2, Purple2, 0, Pink2, 0,
  Purple2, 0, Blue2, Green2, 0, Yellow2, 0, Orange2, LBlue1, 0, Blue1, 0, Purple1, 0, Pink1, 0,
  Orange2, DOrange2, Pink1, 0, Blue1, 0, 0, Pink1, 0, 0, Pink1, 0, 0, 0, Green1, 0, Blue1, 0,
  Pink1, 0, DOrange2, 0, 0, Blue1, 0, 0, Pink1, 0, 0, 0, 0, 0, Orange2, DOrange2, Pink1, 0,
  Blue1, 0, 0, Pink1, 0, 0, Pink1, 0, 0, Green1, 0, 0, DOrange2, 0, Orange2, 0, DOrange2, 0,
  0, Blue1, 0, DOrange1, Yellow1, Green1, DOrange1, Green1, LBlue1, Pink1, Orange2, DOrange2,
  Pink1, 0, Blue1, 0, 0, Pink1, 0, 0, Pink1, 0, 0, 0, Green1, 0, Blue1, 0, Pink1, 0, DOrange2,
  0, 0, Blue1, 0, 0, Pink1, 0, 0, 0, 0, 0, Orange2, DOrange2, Pink1, 0, Blue1, Orange2, 0,
  Green2, Yellow2, Orange2, Pink1, 0, Blue2, LBlue2, 0, Green2, Orange2, DOrange2, 0, Pink1,
  Blue1, Pink1, 0, Blue1, Pink1, 0, Blue1, Pink1, 0, Blue1, Pink1, 0, Blue1, Pink1, Orange2, 0,
  Green2, 0, 0, 0, 0, 0, Orange2, 0, 0, 0, 0, 0, 0, Orange2, Yellow2, LGreen2, 0, 0, Yellow2,
  0, 0, Orange2, 0, DOrange2, 0, 0, Orange2, 0, 0, Yellow2, 0, Green2, 0, 0, 0, 0, 0, Pink2, 0,
  0, 0, 0, 0, Pink1, 0, DOrange2, 0, Orange2, 0, 0, Yellow2, 0, 0, Orange2, 0, DOrange2, 0,
  0, Blue2, 0, 0, DGreen2, 0, Green2, 0, 0, 0, 0, 0, Orange2, 0, 0, 0, 0, 0, 0, Orange2,
  Yellow2, LGreen2, 0, 0, Yellow2, 0, 0, Orange2, 0, DOrange2, 0, 0, Orange2, 0, 0, Yellow2, 0,
  Green2, 0, 0, 0, 0, 0, Pink2, 0, 0, 0, 0, 0, Green2, 0, Purple2, 0, Pink2, 0, 0, DGreen2, 0,
  0, Green2, 0, LGreen2, 0, 0, Pink2, 0, 0, Green2, 0, Green2
};

int L = sizeof(S);
int nds = 10;  // 音符の基本分割数(テンポ調整用)

void setup() {
  Serial.begin(115200);
  pinMode(2, OUTPUT);  // セカンダリへのトリガー出力ピン
  L = L / 2;           // 配列要素数を音符数に変換(intは2バイトのため)
  Serial.println(L);
  Tone();
}

void loop() {}

void Tone() {
  digitalWrite(2, HIGH);  // セカンダリへ演奏開始合図
  for (int n = 0; n < L; n++) {
    int nd = 1000 / nds;          // 1音符の長さ(ミリ秒)
    tone(6, S[n], nd);            // ピン6から音出力
    int d = nd * 1.2;             // 音符間の余裕(1.2倍)
    delay(d);
    noTone(6);
  }
}

パート2:セカンダリArduino(スレーブ)

#include "Color.h"

int S[] = {
  // 最初の長い無音区間(プライマリの前半パートに合わせる)
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  // ここから高音パート(オクターブアップ)が始まる
  Pink2, 0, Pink2, 0, Pink2, Blue2, 0, Pink2, 0, Orange3, 0, Pink2, 0, Green2, Blue2, 0,
  Pink2, 0, Pink2, 0, Pink2, Blue2, 0, Pink2, 0, LGreen3, 0, Yellow3, 0, Orange3, Blue2, 0,
  Pink2, 0, Pink2, 0, Pink2, Blue2, 0, Pink2, 0, Orange3, 0, Pink2, 0, Green2, Blue2, 0,
  Pink2, 0, Pink2, 0, Pink2, 0, Blue2, Pink2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  Orange3, DOrange3, Pink2, 0, Blue2, 0, 0, Pink2, 0, 0, Pink2, 0, 0, 0, Green2, 0, Blue2, 0,
  Pink2, 0, DOrange3, 0, 0, Blue2, 0, 0, Pink2, 0, 0, 0, 0, 0, Orange3, DOrange3, Pink2, 0,
  Blue2, 0, 0, Pink2, 0, 0, Pink2, 0, 0, Green2, 0, 0, DOrange3, 0, Orange3, 0, DOrange3, 0,
  0, Blue2, 0, DOrange2, Yellow2, Green2, DOrange2, Green2, LBlue2, Pink2, Orange3, DOrange3,
  Pink2, 0, Blue2, 0, 0, Pink2, 0, 0, Pink2, 0, 0, 0, Green2, 0, Blue2, 0, Pink2, 0, DOrange3,
  0, 0, Blue2, 0, 0, Pink2, 0, 0, 0, 0, 0, Orange3, DOrange3, Pink2, 0, Blue2, Orange3, 0,
  Green3, Yellow3, Orange3, Pink2, 0, Blue3, LBlue3, 0, Green3, Orange3, DOrange3, 0, Pink2,
  Blue2, Pink2, 0, Blue2, Pink2, 0, Blue2, Pink2, 0, Blue2, Pink2, 0, Blue2, Pink2, Orange3, 0,
  Green2, 0, 0, 0, 0, 0, Orange2, 0, 0, 0, 0, 0, 0, Orange2, Yellow2, LGreen2, 0, 0, Yellow2,
  0, 0, Orange2, 0, DOrange2, 0, 0, Orange2, 0, 0, Yellow2, 0, Green2, 0, 0, 0, 0, 0, Pink2, 0,
  0, 0, 0, 0, Pink1, 0, DOrange2, 0, Orange2, 0, 0, Yellow2, 0, 0, Orange2, 0, DOrange2, 0,
  0, Blue2, 0, 0, DGreen2, 0, Green2, 0, 0, 0, 0, 0, Orange2, 0, 0, 0, 0, 0, 0, Orange2,
  Yellow2, LGreen2, 0, 0, Yellow2, 0, 0, Orange2, 0, DOrange2, 0, 0, Orange2, 0, 0, Yellow2, 0,
  Green2, 0, 0, 0, 0, 0, Pink2, 0, 0, 0, 0, 0, Pink2, 0, DOrange3, 0, Orange3, 0, 0, DGreen3, 0,
  0, Green3, 0, LGreen3, 0, 0, Orange3, 0, 0, Purple2, 0, Pink2
};

int L = sizeof(S);
int nds = 10;

void setup() {
  Serial.begin(115200);
  pinMode(3, INPUT_PULLUP);  // プライマリからのトリガー入力ピン
  L = L / 2;
  Serial.println(L);
}

void loop() {
  if (!digitalRead(3)) {  // トリガー(LOW)を検知したら演奏開始
    Tone();
  }
}

void Tone() {
  for (int n = 0; n < L; n++) {
    int nd = 1000 / nds;
    tone(6, S[n], nd);
    int d = nd * 1.2;
    delay(d);
    noTone(6);
  }
}

回路図

ブレッドボード上の配線図(Fritzing形式)を参照してください。スピーカーはMOSFETを介して駆動し、2台のArduinoはピン2(出力)とピン3(入力プルアップ)で接続されています。

ジョルノのテーマ(Il Vento Doro)をデュアルArduinoで演奏 – 精密なピッチとタイミング
speaker_setup_kNNawzl740.fzz

作り方のポイント

  1. Color.hを用意する: 音名(Pink1, Blue2 など)を周波数(Hz)にマッピングしたヘッダーファイルを作成し、スケッチと同じフォルダに置きます。
  2. 配線: 回路図に従い、2台のArduino、MOSFET、スピーカー、電源をブレッドボード上に組みます。共通GNDを忘れずに。
  3. 書き込み: それぞれのスケッチを対応するボードにアップロードします。
  4. 電源投入: 外部電源(5V)を入れると、プライマリが自動的に演奏を開始し、セカンダリが同期して高音パートを重ねます。

発展のヒント

製造プロセス

  1. TinyML言語検出器:Edge ImpulseとArduino Nano 33 BLE Senseで「はい」を多言語判別
  2. Arduino NanoとMPU-6050で作るリアルタイムジャイロスコープゲーム
  3. Arduinoデジタルダイス: LCD表示の乱数ジェネレーター自作
  4. Arduino Nanoで37LEDルーレットゲームを自作:ヨーロピアンスタイル完全再現
  5. ATtiny85ミニアーケード:スネークゲーム - 手のひらサイズOLEDゲーム機の製作
  6. ポータブル距離検出器:Arduino Nano自作キット(HC-SR04、18650電源、3Dプリントケース付き)
  7. Arduino Nanoで作る音声反応デスクライト:音楽に合わせて光るイルミネーション
  8. Arduino Nano と OpenCV で実現する自律顔追跡ロボットカー
  9. 銅メッキプロジェクト:Arduino UNOで作るスマート電気メッキシステム
  10. Arduino Nanoで作るNeoPixelマトリックス版Pongゲーム
  11. Arduinoシフトレジスタで美しい光のシーケンスを作成