RP2040マイコンを使って、NeoPixelを制御して楽しもうというコンセプトです。
ステレオミニジャックからADコンバータに音声信号を入力してNeoPixelを振幅に合わせて
光らせるサンプルプログラムですが、ADのサンプリングと表示の更新タイミングが
まだまだ調整必要そうなので、うまくいったら更新入れるようにします。
サンプリング間引き過ぎも難しいですね。
ArduinoIDE バージョン:2.3.2
Adafruit NeoPixel Library 1.12.2
①マイコン:PR2040-ZERO(RaspberryPiPico系)
②NeoPixel接続ピン GPI08(R1でショート)
③プッシュスイッチ1:GPI07
④プッシュスイッチ2:GPI06(2個搭載しているボードのみ)
⑤音声入力:GP26
AD入力信号をADコンバータで値を取得して
NeoPixelをレベルによって光らせるサンプルプログラムです。
// ADコンバータ入力とLED制御
#include <Adafruit_NeoPixel.h>
// NeoPixelの設定
#define PIN 8 // NeoPixelのデータピン
#define NUMPIXELS 36 // NeoPixelのLED数
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800); // NeoPixelオブジェクトの作成
// ADコンバータ入力ピン
#define ADC_PIN 26 // ADコンバータの入力ピン
void setup() {
// シリアルモニタの初期化
Serial.begin(115200);
// NeoPixelの初期化
pixels.begin();
pixels.setBrightness(24); // 明るさを24に設定
// ADC_PINを入力モードに設定
pinMode(ADC_PIN, INPUT);
analogReadResolution(12); // ADコンバータの解像度を12ビットに設定
}
void loop() {
// ADコンバータの値を読み取る
int adcValue = analogRead(ADC_PIN);
// シリアルモニタに表示
Serial.println(adcValue);
// NeoPixelの制御
if (adcValue < 2560) {
// 全てのLEDを消灯
pixels.clear();
} else if (adcValue <= 3072) {
// 14, 15, 20, 21を青色に点灯
setPixelsColorRange({14, 15, 20, 21}, pixels.Color(0, 0, 255));
} else if (adcValue <= 3584) {
// 14, 15, 20, 21を青色に点灯
setPixelsColorRange({14, 15, 20, 21}, pixels.Color(0, 0, 255));
// 7, 8, 9, 10, 13, 16, 19, 22, 25, 26, 27, 28を緑色に点灯
setPixelsColorRange({7, 8, 9, 10, 13, 16, 19, 22, 25, 26, 27, 28}, pixels.Color(0, 255, 0));
} else {
// 14, 15, 20, 21を青色に点灯
setPixelsColorRange({14, 15, 20, 21}, pixels.Color(0, 0, 255));
// 7, 8, 9, 10, 13, 16, 19, 22, 25, 26, 27, 28を緑色に点灯
setPixelsColorRange({7, 8, 9, 10, 13, 16, 19, 22, 25, 26, 27, 28}, pixels.Color(0, 255, 0));
// 0, 1, 2, 3, 4, 5, 6, 11, 12, 17, 18, 23, 24, 29, 30, 31, 32, 33, 34, 35を赤色に点灯
setPixelsColorRange({0, 1, 2, 3, 4, 5, 6, 11, 12, 17, 18, 23, 24, 29, 30, 31, 32, 33, 34, 35}, pixels.Color(255, 0, 0));
}
// NeoPixelの更新
pixels.show();
delay(20); // サンプリング間隔を20ミリ秒に設定
}
// 複数のピクセルを同じ色に設定する関数
void setPixelsColorRange(const std::vector<int>& indices, uint32_t color) {
for (int index : indices) {
pixels.setPixelColor(index, color);
}
}
ADコンバータの解像度を12bitに初期設定をして、0から4095でアナログ値を取得するようにしています。
arduinoUNOは、確か10bitでしたのでこの関数は使用するマイコンを選びそうですね。
// ADC_PINを入力モードに設定
pinMode(ADC_PIN, INPUT);
analogReadResolution(12); // ADコンバータの解像度を12ビットに設定
AD変換の結果はシリアルモニタで見ることが可能ですが、
横軸を任意に調整できないのでざっくり確認ですね。
入力にSin波を入力した場合です。
中点は2048付近の信号ということが分かりますね。
振幅は0から4095ぐらいがADコンバータの変換できる範囲になりますね。
入力に三角波を入れてみました。
トップとボトムでサンプリングのタイミングが合わないとこんな感じになってしまうようです。
この辺りは、ADコンバータの取り込み間隔とLEDの更新間隔をバランスが効くようです。
LED表示更新を100msecにするとADコンバータの取り込み間隔が伸びてしまい
更新間隔を短くするとLEDが激しく点滅してしまう感じです。
なるべくADコンバータは取り込み続けてLED表示更新間隔を広げる処理に
しないとLED更新が早過ぎて目がちかちかし過ぎてしまいました。
ADコンバータ結果
2560未満 LED全部消灯。
3072以下 青色の中央4つ点灯
3584以下 緑色で周囲を点灯
それ以上 赤色で最外周を点灯
という設定にしています。
入力信号の振幅が小さい場合は、
ADコンバータの値を調整することで音声の大きさでLEDを光らせることができるようになります。
サンプルプログラムの完成度が低くて申し訳ありません。
今回のサンプルプログラムでADコンバータの値取り込み値からNeoPixelに
音声信号の大きさに合わせて光らせる流れが確認できると思いますので参考にしてみてください。
電脳好奇心 うたたねこ