音声制御LEDプロジェクト:Arduino Micro + BitVoicer Serverで音声認識
必要なパーツと用品
| Arduino Micro | ×1 |
| SparkFun エレクトレットマイク ブレークアウト | ×1 |
| BitVoicer Server | ×1 |
| BitVoicer Server 1.0 | ×1 |
| LED(汎用) | ×3 |
| 抵抗 330Ω | ×3 |
このプロジェクトについて
この記事では、ArduinoボードとBitVoicer Serverを使って、音声コマンドでいくつかのLEDを制御する方法を紹介します。ここではArduino Microを使用していますが、手元にあるどのArduinoボードでも使用可能です。
音声コマンドをLED動作に変換するまでの手順は以下の通りです:
- 音声波がSparkFunエレクトレットブレークアウトボードで取得・増幅される
- 増幅された信号がArduinoのADC(アナログ-デジタルコンバータ)でデジタル化されバッファリングされる
- 音声サンプルがArduinoのシリアルポート経由でBitVoicer Serverにストリーミングされる
- BitVoicer Serverが音声ストリームを処理し、音声認識を行う
- 認識された音声が事前定義されたコマンドにマッピングされ、Arduinoに送り返される
- Arduinoがコマンドを識別し、適切なアクションを実行する
上記の動画はこのプロジェクトの最終結果です。動画内でBitVoicer Serverが音声合成フィードバックも提供しているのがわかります。この音声フィードバックはサーバー側で定義され、サーバーのオーディオアダプターで再生されますが、合成音声をArduinoに送り、DAC(デジタル-アナログコンバータ)で再生することも可能です。次回の記事では、Arduino DUEとアンプ、スピーカーを使って、Arduino自体で合成音声を再生する方法を紹介します。
材料リスト:
- Arduino Micro(または他のArduinoボード): 約$20.00
- SparkFunエレクトレットマイクブレークアウト: $7.95
- BitVoicer Server 1.0: $9.90
- ブレッドボード: 約$10.00
- LED 3個: 約$1.00
- 330Ω抵抗 3個: 約$0.75
- ジャンパーワイヤー: 約$0.30
ステップ1:配線
最初のステップは、以下の写真のようにArduinoとブレッドボードにコンポーネントを配線することです。
(配線写真は元記事を参照)
ここで最も重要なポイントは、ArduinoのADCに供給するアナログ基準電圧です。私のテストでは、SparkFunエレクトレットブレークアウトと組み合わせて3.3Vを使用したときに最良の結果が得られました。そのため、3.3VピンとAREFピンの間にジャンパーワイヤーを接続しています。もし3.3VをAREFピンに印加した状態でanalogRead関数を使用する場合(何らかの理由で)、analogReadを使用する前に必ずanalogReference(EXTERNAL)を呼び出してください。そうしないと、内部で生成されるアクティブな基準電圧とAREFピンが短絡し、Arduinoボード上のマイクロコントローラを破損する可能性があります。
ステップ2:Arduinoへのコードアップロード
以下のコードをArduinoにアップロードします。便宜上、Arduinoスケッチはこの投稿の下部「添付ファイル」セクションにもあります。アップロード前に、BitVoicer ServerライブラリをArduino IDEに正しくインストールしておく必要があります(.zipライブラリのインポート)。
BVS_Demo1.ino
このスケッチは4つの主要部分で構成されています:
- ライブラリ参照と変数宣言: 最初の2行でBVSPとBVSMicライブラリをインクルード。これらはBitSophia提供で、BitVoicer Serverインストールフォルダにあります。その他の行で定数と変数を宣言。BVSPクラスはBitVoicer Serverとの通信用、BVSMicクラスは音声サンプルの取得・蓄積用。
- setup関数: シリアル通信、BVSPクラス、BVSMicクラスを初期化し、frameReceivedイベントの「イベントハンドラ」(関数ポインタ)を設定。
- loop関数: 3つの重要なアクションを実行:サーバーへステータス情報要求(keepAlive())、サーバーからデータ受信チェックと処理(receive())、音声ストリームの録音と送信制御(isSREAvailable()、startRecording()、stopRecording()、sendStream())。
- BVSP_frameReceived関数: receive()関数が完全なフレーム受信を検出すると呼び出される。ここではBitVoicer Serverから送られたコマンドを実行。コマンドは2バイト:1バイト目がピン番号、2バイト目がピン値。
analogWrite()でピンに適切な値を設定。
ステップ3:BitVoicer Serverソリューションオブジェクトのインポート
次に、BitVoicer ServerをArduinoと連携するよう設定します。BitVoicer Serverには4つの主要なソリューションオブジェクトがあります:Locations(場所)、Devices(デバイス)、BinaryData(バイナリデータ)、Voice Schemas(音声スキーマ)。
- Locations: デバイスが設置されている物理的場所を表す。私は「Home」という場所を作成。
- Devices: BitVoicer Serverのクライアント。Mixedデバイスを作成し、「ArduinoMicro」と命名、通信設定を入力。Arduino Microについての注意: RTSとDTRを使用するため、通信タブでこれらを有効化する必要あり。また、サーバーのオーディオアダプターで音声合成を行うSystemSpeakerデバイスも作成。
- BinaryData: BitVoicer Serverがクライアントデバイスに送信できるコマンドタイプの一つ。実際にはコマンドにリンクできるバイト配列。音声認識で該当コマンドに関連する音声が検出されると、ターゲットデバイスにバイト配列が送信される。各ピン値ごとに1つずつBinaryDataオブジェクトを作成(ArduinoMicroGreenLedOn、ArduinoMicroGreenLedOffなど)。最終的に18個のBinaryDataオブジェクトになったため、以下のVoiceSchema.sofファイルからダウンロード・インポートすることを推奨。
- Voice Schemas: すべてが統合される場所。認識すべき文と実行すべきコマンドを定義。1文につき複数のコマンドと実行順序を定義可能。コマンド間の遅延も定義可能。これで動画のような一連のアクションを実現。
この記事で使用したすべてのソリューションオブジェクトは、以下のファイルからインポート(ソリューションオブジェクトのインポート)できます。1つはDevices、もう1つはVoice Schemaとそのコマンドを含みます。
Devices.sof
VoiceSchema.sof
ステップ4:結論
以上です!お楽しみいただけたら幸いです。
動画で示したデモを実行するために必要なものはすべて揃っています。動画では最初にBitVoicer Server ManagerでArduinoMicroデバイスを有効化しています。有効化されるとすぐに、Arduinoが利用可能な音声認識エンジンを検出し、BitVoicer Serverへ音声ストリーミングを開始します。
認識結果はBitVoicer Server ManagerのServer Monitorツールで確認できます。
次回の記事では、Arduino DUEで合成音声を再生する方法を紹介します。
ソースコード (BVS_Demo1.ino)
#include <BVSP.h>
#include <BVSMic.h>
// 音声取得に使用するArduinoピン
#define BVSM_AUDIO_INPUT 5
// LEDピン
#define RED_LED_PIN 6
#define YELLOW_LED_PIN 9
#define GREEN_LED_PIN 10
// BVSP.begin関数に渡す定数
const unsigned long STATUS_REQUEST_TIMEOUT = 1000;
const unsigned long STATUS_REQUEST_INTERVAL = 2000;
// オーディオバッファサイズ
const int AUDIO_BUFFER_SIZE = 64;
// 受信バッファサイズ
const int RECEIVE_BUFFER_SIZE = 2;
// BVSPクラスのグローバルインスタンス
BVSP bvsp = BVSP();
// BVSMicクラスのグローバルインスタンス
BVSMic bvsm = BVSMic();
// BVSMicクラスから録音サンプルを読み取るバッファ
byte audioBuffer[AUDIO_BUFFER_SIZE];
// BitVoicer Serverから送られるコマンドを読み取るバッファ
// バイト0 = ピン番号
// バイト1 = ピン値
byte receiveBuffer[RECEIVE_BUFFER_SIZE];
void setup() {
// ピンモード設定
pinMode(RED_LED_PIN, OUTPUT);
pinMode(YELLOW_LED_PIN, OUTPUT);
pinMode(GREEN_LED_PIN, OUTPUT);
// 115200 bpsでシリアル通信開始
Serial.begin(115200);
// 通信に使用するArduinoシリアルポート、ステータスリクエストのタイムアウト、ステータスリクエスト送信間隔を設定
bvsp.begin(Serial, STATUS_REQUEST_TIMEOUT, STATUS_REQUEST_INTERVAL);
// frameReceivedイベントを処理する関数を定義
bvsp.frameReceived = BVSP_frameReceived;
// BVSMicクラスのタイマー準備
bvsm.begin();
}
void loop() {
// ステータスリクエスト間隔が経過していたら、BitVoicer Serverにステータスリクエスト送信
bvsp.keepAlive();
// シリアルポートバッファにデータがあれば、BitVoicer Serverプロトコル仕様に従って処理
bvsp.receive();
// 利用可能なSRE(音声認識エンジン)があるかチェック。あれば録音開始。
if (bvsp.isSREAvailable()) {
// BVSMicクラスが録音中でなければ、音声入力設定して録音開始
if (!bvsm.isRecording) {
bvsm.setAudioInput(BVSM_AUDIO_INPUT, EXTERNAL);
bvsm.startRecording();
}
// BVSMicクラスに利用可能なサンプルがあるかチェック
if (bvsm.available) {
// 送信モードがSTREAM_MODEであることを確認
if (bvsp.inboundMode == FRAMED_MODE)
bvsp.setInboundMode(STREAM_MODE);
// BVSMicクラスから音声サンプル読み取り
int bytesRead = bvsm.read(audioBuffer, AUDIO_BUFFER_SIZE);
// 音声ストリームをBitVoicer Serverに送信
bvsp.sendStream(audioBuffer, bytesRead);
}
} else {
// SREが利用不可。録音中なら停止。
if (bvsm.isRecording)
bvsm.stopRecording();
}
}
// frameReceivedイベントハンドラ
void BVSP_frameReceived(byte dataType, int payloadSize) {
// 受信フレームがバイナリデータかチェック
// 0x07 = バイナリデータ (バイト配列)
if (dataType == DATA_TYPE_BINARY) {
// 2バイト受信していたらコマンドとして処理
if (bvsp.getReceivedBytes(receiveBuffer, RECEIVE_BUFFER_SIZE) == RECEIVE_BUFFER_SIZE) {
analogWrite(receiveBuffer[0], receiveBuffer[1]);
}
}
}
回路図
(回路図画像は元記事を参照)
製造プロセス
- Python連携で信頼性向上: Arduino RFID勤怠管理システム
- DHT11温湿度センサーで作る温度アラート – LEDとピエゾブザーで視覚/聴覚通知
- Arduino Dueと3.2インチTFTで作る温度監視付きリアルタイムクロック
- ArduinoとAndroidでRoomba Create 2をリモコン操作 ─ Bluetooth経由のステップバイステップガイド
- ArduinoとNokia 5110ディスプレイで自作電圧計:ステップバイステップガイド
- Arduino & MPU6050:SG90 & MG996Rサーボの精密制御
- u-blox LEA-6H 02 GPSモジュール: Arduino & Python 統合ガイド
- DHT11 と Blynk で温湿度をリアルタイム監視する Arduino チュートリアル
- Arduino Dueでマスターする音声認識と音声合成
- Arduino Unoと1Sheeldで作る4x4x4 LEDキューブ – インタラクティブLEDプロジェクト
- Arduino GPS+TFTタッチシールドで作るリアルタイム位置表示デバイス