Yodai Sakai
Published © GPL3+

Make your room groovy! ~with M5StickC-PLUS2~

Don't you ever feel like getting into the mood? LEDs light up in response to sound, creating a live concert-like atmosphere.

IntermediateFull instructions provided3 hours34
Make your room groovy! ~with M5StickC-PLUS2~

Things used in this project

Hardware components

M5Stack M5StickC-Plus2
×1
LED Strip, NeoPixel Digital RGB
LED Strip, NeoPixel Digital RGB
×1

Software apps and online services

VS Code
Microsoft VS Code

Hand tools and fabrication machines

10 Pc. Jumper Wire Kit, 10 cm Long
10 Pc. Jumper Wire Kit, 10 cm Long

Story

Read more

Schematics

配線図

図のように配線します

Code

M5StickCPLUS2_micLED

C/C++
M5StcikCPLUS2に書き込みます
#include <M5Unified.h> 
#include <FastLED.h> 
#include <arduinoFFT.h> 

// --- LEDの設定 --- 
#define LED_PIN     26 
#define NUM_LEDS   300
#define EMP_LEDS   120 
CRGB leds[NUM_LEDS]; 

// --- マイク & FFTの設定 --- 
#define SAMPLES         512 
#define SAMPLING_FREQ 40000 

ArduinoFFT<double> FFT = ArduinoFFT<double>(); 

int16_t* audio_buffer = nullptr; 
double vReal[SAMPLES]; 
double vImag[SAMPLES]; 

// --- 新しいロジックで使う設定値 ---
#define MAX_MAGNITUDE 8000.0 // 反応する音の大きさの最大値。要調整。
#define FFT_BIN_START 0      // 視覚化する周波数範囲の開始点
#define FFT_BIN_END   60    // 視覚化する周波数範囲の終了点

void setup() { 
  M5.begin(); 
  // シリアル通信の開始 (PIOのモニタ用) 
  Serial.begin(115200); 

  M5.Lcd.setRotation(1); 
  M5.Lcd.fillScreen(BLACK); 
  M5.Lcd.setTextSize(2); 
  M5.Lcd.println("Equalizer Viz (PIO)"); 

  audio_buffer = (int16_t*)malloc(sizeof(int16_t) * SAMPLES); 
  if (!audio_buffer) { 
    M5.Lcd.println("Memory failed"); 
    while(1); 
  } 

  M5.Mic.begin(); 

  FastLED.addLeds<NEOPIXEL, LED_PIN>(leds, NUM_LEDS); 
  FastLED.setBrightness(60); 
  FastLED.clear(); 
  FastLED.show(); 
} 

void loop() { 
  // マイクから音声データを読み込む 
  M5.Mic.record(audio_buffer, SAMPLES, SAMPLING_FREQ); 

  // FFTの準備 
  for (int i = 0; i < SAMPLES; i++) { 
    vReal[i] = (double)audio_buffer[i]; 
    vImag[i] = 0; 
  } 

  // FFT計算 
  FFT.windowing(vReal, SAMPLES, FFT_WIN_TYP_HAMMING, FFT_FORWARD); 
  FFT.compute(vReal, vImag, SAMPLES, FFT_FORWARD); 
  FFT.complexToMagnitude(vReal, vImag, SAMPLES); 
   
  // ==================== ここからロジック変更 ====================

  for (int i = 0; i < NUM_LEDS; i++) {
    // このLED (i番目) が担当するFFTビンの範囲を計算
    int start_bin = map(i, 0, NUM_LEDS, FFT_BIN_START, FFT_BIN_END);
    int end_bin = map(i + 1, 0, NUM_LEDS, FFT_BIN_START, FFT_BIN_END);

    // 担当範囲のFFT結果(音の強さ)の平均を求める
    double magnitude_sum = 0;
    for (int j = start_bin; j < end_bin; j++) {
      magnitude_sum += vReal[j];
    }
    double magnitude = magnitude_sum / (end_bin - start_bin);

    // 音の強さに応じて、色(Hue)と明るさ(Brightness)を決定
    magnitude = constrain(magnitude, 0, MAX_MAGNITUDE);

    // 色のマッピング: 弱い(0) => 青(160), 強い(MAX) => 赤(0)
    byte hue = map(magnitude, 0, MAX_MAGNITUDE, 160, 0);
    
    // 明るさのマッピング: 弱い(0) => 暗い(50), 強い(MAX) => 明るい(255)
    byte brightness = map(magnitude, 0, MAX_MAGNITUDE, 9, 255);

    // もし音が非常に小さければ、LEDを消灯する
    if (magnitude < 100) {
      brightness = 0;
    }
    
    // 計算した色と明るさをLEDに設定
    leds[i + EMP_LEDS] = CHSV(hue, 255, brightness);
  }

  // ==================== ここまでロジック変更 ====================

  FastLED.show(); 
  delay(10); 
}

Credits

Yodai Sakai
1 project • 1 follower

Comments