shimodashのアイコン画像
shimodash 2022年09月25日作成 © Apache-2.0
製作品 製作品 閲覧数 788
shimodash 2022年09月25日作成 © Apache-2.0 製作品 製作品 閲覧数 788

SPRESENSEでお菓子の箱がトロンボーンに⁉

SPRESENSEでお菓子の箱がトロンボーンに⁉

はじめに

SPRSENSEのAudio出力機能と最近リリースされたライブラリを使って
ゆる楽器⁉のような物を作ってみました。
測距センサとの組み合わせで「簡単に楽器を開発する」はじめの一歩的な
位置づけで参考にして頂けたらと思います。

材料

  • SPRESENSEメインボード
  • SPRESENSE拡張ボード
  • SDカード
  • 測距センサ VL53L0X
  • スピーカー 及び 音声ケーブル

接続図

接続はシンプルで

  1. メインボード、拡張ボードをスタックします
  2. メインボード上のI2CとVL530Xを接続します
  3. 音声ケーブルとスピーカを接続します

キャプションを入力できます

キャプションを入力できます

プログラム

以下に公開されている
https://github.com/SonySemiconductorSolutions/ssih-music
のサンプルスケッチのButtonDrumを修正しています。
センサの入力を"ただ” VL53L0Xに変更したものです。

VL53L0Xのライブラリはライブラリのダウンロードでこちらを使っています。
キャプションを入力できます

サンプルプログラム

/* * SPDX-License-Identifier: (Apache-2.0 OR LGPL-2.1-or-later) * * Copyright 2022 Sony Semiconductor Solutions Corporation */ #ifndef ARDUINO_ARCH_SPRESENSE #error "Board selection is wrong!!" #endif #ifdef SUBCORE #error "Core selection is wrong!!" #endif #include <MemoryUtil.h> #include <SDSink.h> //sensor #include <Wire.h> #include <VL53L0X.h> VL53L0X sensor; // this file names are deifned middle C (60) as C4 const SDSink::Item table[12] = { {60, "SawLpf/60_C4.wav"}, // C4 {61, "SawLpf/61_C#4.wav"}, // C#4 {62, "SawLpf/62_D4.wav"}, // D4 {63, "SawLpf/63_D#4.wav"}, // D#4 {64, "SawLpf/64_E4.wav"}, // E4 {65, "SawLpf/65_F4.wav"}, // F4 {66, "SawLpf/66_F#4.wav"}, // F#4 {67, "SawLpf/67_G4.wav"}, // G4 {68, "SawLpf/68_G#4.wav"}, // G#4 {69, "SawLpf/69_A4.wav"}, // A4 {70, "SawLpf/70_A#4.wav"}, // A#4 {71, "SawLpf/71_B4.wav"} // B4 }; SDSink inst(table, 12); int selector = 0; int button4 = HIGH; int button5 = HIGH; int button6 = HIGH; void setup() { // init built-in I/O Serial.begin(115200); pinMode(LED0, OUTPUT); pinMode(LED1, OUTPUT); pinMode(LED2, OUTPUT); pinMode(LED3, OUTPUT); // init buttons pinMode(PIN_D04, INPUT_PULLUP); pinMode(PIN_D05, INPUT_PULLUP); pinMode(PIN_D06, INPUT_PULLUP); // initialize memory pool initMemoryPools(); createStaticPools(MEM_LAYOUT_RECORDINGPLAYER); // setup instrument if (!inst.begin()) { Serial.println("ERROR: init error."); while (true) { delay(1000); } } Serial.println("Ready to play ButtonDrum"); // VL53L0X setup // Serial.begin(9600); Wire.begin(); sensor.setTimeout(500); if (!sensor.init()) { Serial.println("Failed to detect and initialize sensor!"); while (1) {} } // Start continuous back-to-back mode (take readings as // fast as possible). To use continuous timed mode // instead, provide a desired inter-measurement period in // ms (e.g. sensor.startContinuous(100)). sensor.startContinuous(); } int note1 = INVALID_NOTE_NUMBER; void loop() { Serial.print(sensor.readRangeContinuousMillimeters()); if (sensor.timeoutOccurred()) { Serial.print(" TIMEOUT"); } Serial.println(); int distance_input = sensor.readRangeContinuousMillimeters(); //測定している距離が一定の距離に入ったら音を出すようにする。以下は 100mm未満 if (distance_input < 100 ) { //距離を12等分したものを割って、小数点が切り捨てられるようにし60に加算 //値が72になるとエラーし暴走してしまうので注意 note1 = 60 + int(float(distance_input / (100 / 12.0)-0.5)); Serial.println(note1); inst.sendNoteOn(note1, DEFAULT_VELOCITY, DEFAULT_CHANNEL); } else { inst.sendNoteOff(note1, DEFAULT_VELOCITY, DEFAULT_CHANNEL); } // run instrument inst.update(); }

動作

ここに動画が表示されます

最後に

SPRESENSEはカメラの搭載できるので
お菓子の箱を認識して音色や音階を変化する距離を
自動変更できたら、面白いかなと思います。
すみません、そこまで作り込めなかったのですが
アイデアの種として共有させて頂けたらと思います。

箱に応じた機能変更

1
shimodashのアイコン画像
会社員をしています。 Myms-techという活動名で、子供向けの電子工作ワークショップを しています。 URLは https://shimodash.github.io/Myms-tech facebookは https://www.facebook.com/mymstech twitterは https://twitter.com/shimodash_home もしよかったらSNSフォローを ※発言は個人的なものです。
  • shimodash さんが 2022/09/25 に 編集 をしました。 (メッセージ: 初版)
  • Opening
    shimodashのアイコン画像 shimodash 2022/12/04

    https://github.com/SonySemiconductorSolutions/ssih-music
    のバージョンが0.9.0にアップデートされたのと、
    同じ音階の時は音が延長されるように、修正をしました。

    あと、お菓子の箱の距離では、、、音階変更がシビアなので
    距離を測るレンジを3倍の30cmに変更しています。

    ソースコードはこちらになります。

    /* * SPDX-License-Identifier: (Apache-2.0 OR LGPL-2.1-or-later) * * Copyright 2022 Sony Semiconductor Solutions Corporation */ #ifndef ARDUINO_ARCH_SPRESENSE #error "Board selection is wrong!!" #endif #ifdef SUBCORE #error "Core selection is wrong!!" #endif #include <MemoryUtil.h> #include <SDSink.h> //sensor #include <Wire.h> #include <VL53L0X.h> VL53L0X sensor; // this file names are deifned middle C (60) as C4 const SDSink::Item table[12] = { {60, "SawLpf/60_C4.wav"}, // C4 {61, "SawLpf/61_C#4.wav"}, // C#4 {62, "SawLpf/62_D4.wav"}, // D4 {63, "SawLpf/63_D#4.wav"}, // D#4 {64, "SawLpf/64_E4.wav"}, // E4 {65, "SawLpf/65_F4.wav"}, // F4 {66, "SawLpf/66_F#4.wav"}, // F#4 {67, "SawLpf/67_G4.wav"}, // G4 {68, "SawLpf/68_G#4.wav"}, // G#4 {69, "SawLpf/69_A4.wav"}, // A4 {70, "SawLpf/70_A#4.wav"}, // A#4 {71, "SawLpf/71_B4.wav"} // B4 }; SDSink inst(table, 12); int selector = 0; int button4 = HIGH; int button5 = HIGH; int button6 = HIGH; void setup() { // init built-in I/O Serial.begin(115200); pinMode(LED0, OUTPUT); pinMode(LED1, OUTPUT); pinMode(LED2, OUTPUT); pinMode(LED3, OUTPUT); // init buttons pinMode(PIN_D04, INPUT_PULLUP); pinMode(PIN_D05, INPUT_PULLUP); pinMode(PIN_D06, INPUT_PULLUP); // initialize memory pool // initMemoryPools(); // createStaticPools(MEM_LAYOUT_RECORDINGPLAYER); // setup instrument if (!inst.begin()) { Serial.println("ERROR: init error."); while (true) { delay(1000); } } Serial.println("Ready to play DistDrum"); // VL53L0X setup // Serial.begin(9600); Wire.begin(); sensor.setTimeout(500); if (!sensor.init()) { Serial.println("Failed to detect and initialize sensor!"); while (1) {} } // Start continuous back-to-back mode (take readings as // fast as possible). To use continuous timed mode // instead, provide a desired inter-measurement period in // ms (e.g. sensor.startContinuous(100)). sensor.startContinuous(); // inst.sendNoteOn(61, DEFAULT_VELOCITY, DEFAULT_CHANNEL); // inst.update(); // delay(1000); } int note1 = INVALID_NOTE_NUMBER; int pre_note1 = INVALID_NOTE_NUMBER; void loop() { // Serial.print(sensor.readRangeContinuousMillimeters()); if (sensor.timeoutOccurred()) { Serial.print(" TIMEOUT"); } // Serial.println(); int distance_input = sensor.readRangeContinuousMillimeters(); //測定している距離が一定の距離に入ったら音を出すようにする。以下は 300mm未満 if (distance_input < 300 ) { //距離を12等分したものを割って、小数点が切り捨てられるようにし60に加算 //値が72になるとエラーし暴走してしまうので注意 note1 = 60 + int(float(distance_input / (300 / 12.0)-0.5)); Serial.println(note1); if(note1 != pre_note1){ inst.sendNoteOff(pre_note1, DEFAULT_VELOCITY, DEFAULT_CHANNEL); inst.sendNoteOn(note1, DEFAULT_VELOCITY, DEFAULT_CHANNEL); } pre_note1 = note1; } inst.update(); }
    0 件の返信が折りたたまれています
ログインしてコメントを投稿する