ESP8266 + ws2812 编写声控子弹灯的代码
时间: 2024-04-26 16:22:27 浏览: 10
以下是基于Arduino平台编写的ESP8266 + ws2812声控子弹灯代码:
```c++
#include <Adafruit_NeoPixel.h>
#include <ArduinoFFT.h>
#define LED_PIN 4 // ws2812所连接的GPIO引脚
#define LED_COUNT 60 // ws2812的数量
#define BRIGHTNESS 255 // 亮度值,取值范围0-255
#define SAMPLES 256 // 采样点数
#define SAMPLING_FREQUENCY 8000 // 采样频率,单位为Hz
#define FFT_SCALE_FACTOR 50 // FFT结果放大倍数
#define MIN_FREQ 20 // 声音频率的最小值
#define MAX_FREQ 2000 // 声音频率的最大值
#define DELAY_TIME 20 // 每个灯亮起的时间间隔,单位为毫秒
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
ArduinoFFT FFT = ArduinoFFT();
byte sampleBuffer[SAMPLES];
void setup() {
strip.begin();
strip.setBrightness(BRIGHTNESS);
strip.show(); // 初始化,关闭所有灯
Serial.begin(115200);
}
void loop() {
// 读取声音数据
for(int i=0; i<SAMPLES; i++) {
sampleBuffer[i] = analogRead(A0) / 4; // 读取A0引脚的模拟值,并将其缩小4倍
delayMicroseconds(1000000 / SAMPLING_FREQUENCY); // 采样时间间隔,单位为微秒
}
// 进行FFT分析
FFT.Windowing(sampleBuffer, SAMPLES, FFT_WIN_TYP_HAMMING, FFT_FORWARD);
FFT.Compute(sampleBuffer, SAMPLES, FFT_FORWARD);
double real, imag;
for(int i=0; i<SAMPLES/2; i++) {
FFT.GetResult(i, real, imag);
double magnitude = sqrt(real*real + imag*imag);
sampleBuffer[i] = (byte)(magnitude / FFT_SCALE_FACTOR); // 对FFT结果进行放大,得到频率幅值
}
// 找到最大频率
int maxFreq = 0;
byte maxFreqMag = 0;
for(int i=MIN_FREQ*SAMPLES/SAMPLING_FREQUENCY; i<MAX_FREQ*SAMPLES/SAMPLING_FREQUENCY; i++) {
if(sampleBuffer[i] > maxFreqMag) {
maxFreqMag = sampleBuffer[i];
maxFreq = i * SAMPLING_FREQUENCY / SAMPLES;
}
}
// 控制LED亮灭
if(maxFreq > 0) {
int ledIndex = map(maxFreq, MIN_FREQ, MAX_FREQ, 0, LED_COUNT-1); // 将频率映射到LED序号
strip.setPixelColor(ledIndex, strip.Color(255, 0, 0)); // 设置当前灯的颜色为红色
strip.show(); // 点亮当前灯
delay(DELAY_TIME); // 延时
strip.setPixelColor(ledIndex, strip.Color(0, 0, 0)); // 关闭当前灯
}
}
```
该代码通过读取A0引脚的模拟值,进行FFT分析,得到声音的频率分布情况,并将最大频率映射到LED序号,控制对应的LED灯亮灭。可以根据实际需求,修改亮灯颜色、亮灯时间间隔等参数。需要注意的是,该代码需要连接一个麦克风模块,将其输出连接到ESP8266的A0引脚上。