Arduino Nano 33 BLE Senseで音声データ伝送を実現する方法
必要な部品と材料
![]() |
Arduino Nano 33 BLE Sense | × | 1 |
このプロジェクトについて
Chirpのチームは、Arduinoが多様なセンサー、強力なプロセッサー、そして何よりオンボードマイクを搭載した新しいボードを発表したとき、大きな期待を抱きました。Arduinoのご厚意でNano 33 BLE Senseのプレリリース版を提供していただき、これはChirpと完全に互換性があるため、メイカーコミュニティが音を使ってデータの送受信を行えるようになりました。
ChirpはArduinoボードにまったく新しい伝送メカニズムを追加します。音によるデータ伝送の利点には以下のようなものがあります:
- デバイス非依存: モバイルアプリ、Webページ、あるいは単なる音声ファイルからデータを送信可能
- 一対多: 聞こえる範囲内のあらゆるデバイスが一度のトランザクションでデータを受信
- 摩擦なし: ペアリング、パスワード、初期設定が一切不要
このチュートリアルでは、Chirp SDKを使用してRGB値を送信し、オンボードLEDの色を変更する方法を実演します。Chirpは長年の研究によりデコーダーが背景音に対して堅牢であるため、騒がしい場所でも動作します。詳細についてはこちらをご覧ください。
まだ懐疑的な方は、実際に試してみてください。Chirpの導入はこれまで以上に簡単です...
始めるには
まだの場合は、developers.chirp.ioでChirpにサインアップしてください。サインアップ後、アプリケーション用のアプリキー、シークレット、オーディオ設定を取得できます。
データの受信
Nano 33 Senseにはオンボードマイクが搭載されているため、Chirpでデータを受信するにはライブラリマネージャーから直接入手できるChirp SDKのみが必要です。
ライブラリマネージャーを開き、「Chirp SDK」で検索してください。v3.3.0以降をインストールすれば、すぐにコーディングを開始できます。
ツール > ライブラリを管理
まずはサンプルコードを開いてみましょう。
ファイル > スケッチ例 > ChirpSDK > Nano33SenseReceive
credentials.hファイルに、developers.chirp.ioから取得した16khz-mono-embeddedプロトコルの認証情報をコピー&ペーストしてください。
サンプルコードは受信したデータをシリアルモニターに出力するだけですが、onReceivedCallback関数を編集することで、オンボードLEDを点灯させる動作に変更できます。
setup関数で、LEDに接続されたGPIOピンを出力に設定します:
#define R_LED_PIN 22
#define G_LED_PIN 23
#define B_LED_PIN 24
void setup() {
pinMode(R_LED_PIN, OUTPUT);
pinMode(G_LED_PIN, OUTPUT);
pinMode(B_LED_PIN, OUTPUT);
}
データペイロードからRGB値を取り出してLEDを駆動します:
void onReceivedCallback(void *chirp, uint8_t *payload, size_t length, uint8_t channel) {
if (length > 0) {
// 値が大きいほど暗くなるため、UINT8_MAXから減算
analogWrite(R_LED_PIN, UINT8_MAX - payload[0]);
analogWrite(G_LED_PIN, UINT8_MAX - payload[1]);
analogWrite(B_LED_PIN, UINT8_MAX - payload[2]);
} else {
Serial.println("Decode failed");
}
}
以下の音声ファイルを再生してコードをテストできます。それぞれLEDの色を赤→緑→青と変化させます。
次のステップ
Arduino用Chirp SDKの最初のバージョンは、可聴域の16khz-mono-embeddedプロトコルでのみ動作します。今後数ヶ月で、人間には聞こえない準超音波周波数で動作する非可聴バージョンをリリース予定です。これにより、楽曲や動画など既存のオーディオにChirpデータを埋め込んでアクションをトリガーするといった用途が可能になります。
また、Arduinoでデータオーバーサウンドを活用するさらなるチュートリアルも予定しています。ご自身のArduinoプロジェクトでChirpを使用した事例があれば、Twitterで@chirpをタグ付けするか、contact@chirp.ioまでご連絡ください。
コード
ChirpでNano 33 SenseにRGB値を送信 C/C++
Chirpを使用してRGB値を送信し、オンボードLEDの色を変更します。このチュートリアルに添付のサウンドクリップを使用するか、3バイトの配列を送信して自分で試すことができます。
/**--------------------------------------------------------------------
Arduino Nano 33 Senseボードでデータを受信するサンプルコード
@file Nano33SenseReceive.ino
@brief https://developers.chirp.ioで開発者アカウントを作成し、
「16khz-mono-embedded」プロトコルのキー、シークレット、設定文字列を
以下のchirp定義にコピー&ペーストしてください。
このサンプルはRGB値をリッスンし、オンボードLEDの色を変更します。
回路:
- Arduino Nano 33 BLEボード
Copyright © 2011-2019, Asio Ltd. All rights reserved.
-------------------------------------------------------------------*/
#include <PDM.h>
#include "chirp_connect.h"
#define CHIRP_APP_KEY "YOUR_APP_KEY"
#define CHIRP_APP_SECRET "YOUR_APP_SECRET"
#define CHIRP_APP_CONFIG "YOUR_APP_CONFIG"
#define SAMPLE_RATE 16000
#define BUFFER_SIZE 256
#define R_LED_PIN 22
#define G_LED_PIN 23
#define B_LED_PIN 24
// グローバル変数
static chirp_connect_t *chirp = NULL;
short sampleBuffer[BUFFER_SIZE];
volatile int samplesRead;
// 関数定義
void setupChirp(void);
void chirpErrorHandler(chirp_connect_error_code_t code);
void onPDMdata(void);
// メイン
void setup() {
Serial.begin(115200);
// while (!Serial);
pinMode(R_LED_PIN, OUTPUT);
pinMode(G_LED_PIN, OUTPUT);
pinMode(B_LED_PIN, OUTPUT);
setupChirp();
PDM.onReceive(onPDMdata);
PDM.setGain(30);
if (!PDM.begin(1, SAMPLE_RATE)) {
Serial.println("Failed to start PDM!");
while (1);
}
analogWrite(R_LED_PIN, UINT8_MAX);
analogWrite(G_LED_PIN, UINT8_MAX);
analogWrite(B_LED_PIN, UINT8_MAX);
}
void loop() {
if (samplesRead) {
chirp_connect_error_code_t err = chirp_connect_process_shorts_input(chirp, sampleBuffer, samplesRead);
chirpErrorHandler(err);
samplesRead = 0;
}
}
void onPDMdata() {
int bytesAvailable = PDM.available();
PDM.read(sampleBuffer, bytesAvailable);
samplesRead = bytesAvailable / sizeof(short);
}
// Chirpコールバック
void onReceivingCallback(void *chirp, uint8_t *payload, size_t length, uint8_t channel) {
Serial.println("Receiving data...");
analogWrite(R_LED_PIN, UINT8_MAX);
analogWrite(G_LED_PIN, UINT8_MAX);
analogWrite(B_LED_PIN, UINT8_MAX);
}
void onReceivedCallback(void *chirp, uint8_t *payload, size_t length, uint8_t channel) {
if (length) {
// 値が大きいほど暗くなるため、UINT8_MAXから減算
analogWrite(R_LED_PIN, UINT8_MAX - payload[0]);
analogWrite(G_LED_PIN, UINT8_MAX - payload[1]);
analogWrite(B_LED_PIN, UINT8_MAX - payload[2]);
} else {
analogWrite(R_LED_PIN, 0);
analogWrite(G_LED_PIN, UINT8_MAX);
analogWrite(B_LED_PIN, UINT8_MAX);
delay(500);
analogWrite(R_LED_PIN, UINT8_MAX);
delay(500);
analogWrite(R_LED_PIN, 0);
Serial.println("Decode failed");
}
}
void chirpErrorHandler(chirp_connect_error_code_t code) {
if (code != CHIRP_CONNECT_OK) {
const char *error_string = chirp_connect_error_code_to_string(code);
Serial.println(error_string);
exit(42);
}
}
void setupChirp(void) {
chirp = new_chirp_connect(CHIRP_APP_KEY, CHIRP_APP_SECRET);
if (chirp == NULL) {
Serial.println("Chirp initialisation failed.");
return;
}
chirp_connect_error_code_t err = chirp_connect_set_config(chirp, CHIRP_APP_CONFIG);
chirpErrorHandler(err);
char *info = chirp_connect_get_info(chirp);
Serial.println(info);
chirp_connect_free(info);
chirp_connect_callback_set_t callback_set = {
.on_state_changed = NULL,
.on_sending = NULL,
.on_sent = NULL,
.on_receiving = onReceivingCallback,
.on_received = onReceivedCallback
};
err = chirp_connect_set_callbacks(chirp, callback_set);
chirpErrorHandler(err);
err = chirp_connect_set_input_sample_rate(chirp, SAMPLE_RATE);
chirpErrorHandler(err);
err = chirp_connect_set_frequency_correction(chirp, 1.0096);
chirpErrorHandler(err);
err = chirp_connect_start(chirp);
chirpErrorHandler(err);
Serial.println("Chirp SDK initialised.");
Serial.flush();
}
製造プロセス
- リアルタイムデータインサイトでデジタル製造チームを変革する
- LPレコード製造の芸術とプロセス
- センサーデータをRaspberry Piに統合:実践ガイド
- 高度なHMIでプラントエネルギー効率を最大化
- データ侵害の8つの典型タイプ:実例と影響を徹底解説
- 最先端インダストリー4.0テクノロジー:実世界のイノベーションと応用
- 「信頼性のインターネット」におけるデータ活用:効果的管理のための戦略
- エッジ時代のIoT:成長、データ、セキュリティ、パートナー戦略
- インダストリー4.0を昇華:エッジアナリティクスでよりスマートで速い製造を実現
- リアルタイム都市データを活用したスマートシティイノベーション
- C++ char型をマスター:宣言、ASCII、変換テクニック
