ビリーバスフィッシュを任意の音源で動かす:ステップバイステップガイド
必要な部品と用品
| 部品 | 説明 | 数量 |
|---|---|---|
| Arduino Uno | 1 | |
| Adafruit Motor/Stepper/Servo Shield v2.3 | 1 | |
| Amazon Echo Dot | 1 |
プロジェクト概要
約1ヶ月前、アーティストのBrian Kane氏が「ビッグマウス・ビリーバス」というおしゃべり魚のおもちゃをAmazon Alexaで動かす動画を公開し、話題になりました。仕組みを知りたくて、自分でも作ってみることにしました。
最初はRaspberry PiとAlexaを組み合わせたものかと思いましたが、より簡単な方法として、50ドルのEcho Dotの音声をArduinoで処理し、既存のモーターを駆動する方法を考えました。手元にArduinoとモーターシールドがあったので、早速取り掛かりました。
中古のビリーバスをAmazonで約15ドルで購入(ヤードセールやリサイクルショップならもっと安く手に入ります)。参考にしたのは、Arduinoでサーボを音に合わせて動かす2012年のガイドと、ビリーバスのアニマトロニクス構造を解説した2013年のガイドです。
ビリーバスは2つの安価な5V DCモーターで動いています(フルビーと同様)。課題は、音に反応してこれらのモーターをピクピク動かす方法です。試行錯誤の末、実用的な解決策を見つけました。コードは完璧ではありませんが、皆さんの改善アイデアを期待して公開します。
必要な材料
- ビッグマウス・ビリーバス(歌う魚) ×1
- Arduino Uno ×1
- Arduino Uno用電源 ×1
- Adafruit Motor Shield v2 ×1
- パネルマウント ミニジャック ×1
- 撚り線(色分けされていると便利)
- Amazon Echo Dot(他の音源でも可) ×1
- 小型充電式スピーカー ×1
- ミニジャック(⅛インチ)オーディオケーブル ×1
- ミニジャック分岐アダプター ×1
必要な工具
- 小型ドライバー
- はんだごてとはんだ
- ワイヤーストリッパー
- ニッパー
- ドリルとビット
ステップ1:魚の準備
購入した中古品は到着時に動作しませんでした。おかげで躊躇なく分解できました。背面のネジを外し、ケーブルハーネスを優しく押して外せば、背面カバーが完全に取れます。
電子部品を入れるスペースを確保するため、基板とピエゾブザーを取り外します。残るのは4線のハーネスで、2本は口の動き用、もう2本は頭または尻尾を動かす用です(モーターの回転方向で切り替え)。
最後に、異なる色の線を4本同じ長さに切り、先端を露出・予備はんだし、ハーネスの4つのソケットに差し込みます。次のステップでモーターシールドに接続します。
ステップ2:モーターシールドの準備
モーターシールドへの接続は4箇所のみで、うち2箇所ははんだ付けが必要です。頭/尻尾用モーターも実験したい場合はさらに2線追加できます。
まずはんだ付けから。オーディオ入力を作るため、異なる色の線を2本用意し、片方をGND、もう片方をアナログピン0(A0)にはんだ付けします。基板を貫通する余分な線はカットします。
これらをパネルマウントミニジャックに接続します。私が使ったのは3つの接点があるスイッチ付きモノラルジャックです。重要なのは、A0からの線をオーディオコネクタのチップ(先端)に接触するリードに、GNDの線をベース(スリーブ)に接触するリードに接続することです。
次に、魚のモーターをシールドに接続します。口用モーターの線(黒とオレンジ/黄色)をM1の端子ブロックに、オプションで頭/尻尾用モーターの線(白と赤)をM2の端子ブロックに接続し、ネジで固定します。
最後に、モーターシールドの「VIN Jumper」ピンにジャンパーが装着されているか確認してください。これが外れているとシールドが電源オンになりません。Arduino Unoにシールドを重ね、電源を入れてシールドの電源LEDが点灯すればOKです。
ステップ3:コードの書き込み
コードはAdafruitのDCモーターテストスケッチと、Cenk Özdemir氏の「Sound to Servo」スケッチ(2012年)を組み合わせたものです。現在のコードでは頭/尻尾モーターは動きません。動くバージョンもありましたが、口の反応速度が犠牲になりました。口の反応を維持しつつ頭と尻尾をゆっくり動かすのが目標ですが、現状の私のコーディングスキルでは限界です。改善案やプルリクエストを歓迎します。
ステップ4:組み立て
コードを書き込み、オーディオケーブルをジャックに接続したら、フリーのケーブル端を音源(スマホでポッドキャスト再生など)につないでテストします。魚の口が動けば成功です。プラスチックの台座に小さな穴を開け、ジャックを取り付けます。
Alexaの声を魚から出すには、オーディオケーブルのフリー端をYアダプターに、充電式スピーカーをもう一方に、アダプターのプラグをEcho Dotの音声出力に接続します。
スピーカーの電源を入れ、Alexaとスピーカーの音量を上げます。Alexaに質問して喋らせると、スピーカーから声が出ると同時に魚の唇が動きます。スピーカーを魚の頭に近づけるとより不気味で面白い効果が得られます。
動作確認後、スピーカーとArduinoをビリーバスの筐体に収めて蓋をします。この部分はまだ改善の余地があります。
ステップ5:今後の展望
まだまだやることはたくさんあります。皆さんのアイデアをお待ちしています。近いうちにバージョン2.0を公開したいと思います。
- 頭と尻尾も動かしたい。接続はできているが、口の反応速度を落とさずに動かす方法が見つかっていない。
- スピーカーをArduinoから充電できるようにしたい。
- 魚の赤いボタン(または代替スイッチ)で「スピーチモード」(口の動き重視)と「ミュージックモード」(全身でリズムを取る)を切り替えられるようにしたい。
- コードの整理。マッシュアップによる不要なコードが残っているはず。
- より小型のArduinoを使用。Unoとモーターシールドはオーバースペック。Adafruit Featherとその2モーターシールドが良い代替案。口用と頭/尻尾用で別々のFeatherを使うのもアリ。
コード
SoundToDC (Arduino)
/* 音に合わせてDCモーターを動かす。パブリックドメイン。
Donald Bell, Maker Project Lab (2016)作成。
Cenk ÖzdemirのSound to Servo (2012)とAdafruitのDCMotorTestをベースにしている。 */
#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_MS_PWMServoDriver.h"
// デフォルトのI2Cアドレスでモーターシールドオブジェクトを作成
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
// 別のI2Cアドレスを使う場合(スタッキング時など)
// Adafruit_MotorShield AFMS = Adafruit_MotorShield(0x61);
// ポートM1(口)、M2(尻尾)を選択
Adafruit_DCMotor *myMotor = AFMS.getMotor(1);
Adafruit_DCMotor *myOtherMotor = AFMS.getMotor(2);
int SoundInPin = A0;
int LedPin = 12; // 口が動く時にLEDを光らせたい場合
void setup() {
Serial.begin(9600);
AFMS.begin(); // デフォルト周波数1.6kHz
// AFMS.begin(1000); // 1kHzなどに変更も可能
myMotor->setSpeed(0);
myMotor->run(FORWARD);
myMotor->run(RELEASE);
pinMode(SoundInPin, INPUT);
pinMode(LedPin, OUTPUT);
myOtherMotor->setSpeed(0);
myOtherMotor->run(FORWARD);
myOtherMotor->run(RELEASE);
pinMode(SoundInPin, INPUT);
}
void loop() {
uint8_t i;
int sensorValue = analogRead(SoundInPin);
// LED用に0-255にマッピング
int LEDValue = map(sensorValue, 0, 512, 0, 255);
// モーター制御用に0-180にマッピング(通常は1023だが512に変更して感度向上)
sensorValue = map(sensorValue, 0, 512, 0, 180);
// モーター駆動時間の計算
int MoveDelayValue = map(sensorValue, 0, 255, 0, sensorValue);
if (sensorValue > 10) { // ノイズ除去
delay(1);
myMotor->run(FORWARD);
for (i = 140; i < 255; i++) {
myMotor->setSpeed(i);
}
// 減速パートはコメントアウト
// for (i = 200; i != 0; i--) {
// myMotor->setSpeed(i);
// delay(10);
// }
analogWrite(LedPin, sensorValue);
myMotor->run(RELEASE);
myOtherMotor->run(RELEASE);
delay(1);
}
analogWrite(LedPin, 0);
// これを繰り返す
}
製造プロセス
- K30 CO2センサで室内空気質をリアルタイム監視する
- 1SheeldとArduinoで盲ろう者のコミュニケーションを支援する
- スマート貯金箱を作ろう:Arduino Nanoでコインアクセプターを制御
- ビッグマウス・ビリーバスをAlexa対応に改造 - Arduino、L293Dシールド、LM386アンプで実現
- Arduinoオーディオ周波数検出器 – 高感度サウンドモジュールで最大音量ピークの周波数を測定
- ArduinoでBluetooth経由でLEDを制御 – シンプルDIYガイド
- DFRobot静電容量式指紋センサーをArduino/ESP8266で使う – 登録・認証・削除の完全ガイド
- Arduino MegaとNextion HMIで作る高機能ウェザーステーション
- Arduino UNOとDFPlayer Miniで音声を再生する方法 - ステップバイステップガイド
- Arduinoベースのヌンチャク操作6自由度ロボットアームキット
- Arduino UNOとEthernetシールドで太陽放射を測定する自作ピラノメーター