【Arduino 动手做】ESP32 带有 INMP441 的 WS2812B 矩阵
ESP32-INMP441-Matrix-VU重要提示:目前,该代码仅适用于 ESP32 核心 1.0.6,在 2.0.0 上不可靠。我认为这是一个 FastLED 问题,但我可能错了!使用 Boards Manager 恢复到 1.0.6 以便编译和上传。
这是 3D 打印的(可选)电池供电的 WS2812B LED 矩阵的存储库,它使用来自 INMP441 数字麦克风的音频输入产生漂亮的图案,并在 ESP32 上运行。在下面的 YouTube 链接中观看解释视频:
硬件
您至少需要:
可以使用用于生产外壳的 3D 打印机,STL。
ESP32 开发板,确切的类型并不重要。
一个 8x8 (80x80 mm) 或 16x16 (160x160 mm) WS2812B LED 矩阵。
我的代码应该适用于宽度为 8 或 16 的倍数的任何矩阵。高度并不重要。如果您使用的是 WLED,您可以拥有任何您喜欢的尺寸!
我的矩阵的数据输入位于左下角,并以水平之字形模式连接。
INMP441 I2S 麦克风。
电源开关
DC 输入插座和 5V 电源(如果您不是由电池供电)。
建造它的常用电子设备和设备。
无电池原理图
如果您想为您的创作提供电池,您还需要:
LiPo / LiIon 电池 - 确切规格取决于您需要的运行时间以及您用于充电/升压电路的解决方案。
一个充电/升压板,用于连接您的电池并为 LED 输出 5V。
或者,您可以为这些函数使用单独的模块,这对于更高功率的 16x16 矩阵来说可能是一个好主意。
电池原理图
软件
关于软件,您有两个主要选择,此存储库中给出的软件或 WLED Sound Reactive fork。任一选项的硬件连接都是相同的。与该软件相比,使用 WLED 有很多优点,它是一个更完整的解决方案,可以更好地支持同步多个控制器、设置模式播放列表和自定义现有的模式。我的软件唯一真正的优势是我想编写自己的模式,并且能够完全自定义事情的运作方式。您可以自由选择。如果您想使用我的软件,请继续阅读...
软件设置
下载代码,并确保已安装所有必需的库。它们列在 .ino 文件的顶部。
确保在软件中正确设置了矩阵的输入位置和接线样式。有关更多详细信息,请参阅 .ino 文件顶部的注释。
将 和 更改为矩阵的正确 LED 数量。M_WIDTHM_HEIGHT
进入 web_server.h 并将 、 、 和 更改为您的主网络凭证和备用网络凭证。ssidpasswordssid2password2
将代码上传到您的 ESP32 并希望一切顺利!
使用矩阵
每次您为矩阵供电时,它都会尝试连接到主 WiFi 网络 5 秒钟。如果失败,它将尝试辅助凭证 5 秒钟。如果此作也失败,它将回退到之前的设置,但您将无法进行任何更改。我已将辅助凭证设置为手机上的热点,因此我可以在家庭网络之外使用该设备。 如果成功连接到网络,ESP 的本地 IP 将在屏幕上滚动。在任何浏览器中转到此地址以更改设置。可以更改的设置包括:
下一个模式 - 不言自明。
Auto-change pattern (自动更改模式) - 将每隔几秒循环一次模式,定义如下...
在 auto 上显示每个模式的秒数 - 接受 1 到 65535 秒之间的值
亮度 - 在这里要小心,在最大亮度下,较大的面板可能会消耗许多安培。确保您的电源能够胜任工作!
增益 - 提高麦克风的灵敏度,以适应更响亮或更安静的环境。
静噪 - 增加此值会限制将拾取的最安静的声音。如果您有一些背景噪音要消除,则很有用。 这些设置保存在 EEPROM 中,因此它们在重启后应保持不变。
【Arduino 动手做】ESP32 带有 INMP441 的 WS2812B 矩阵
项目代码/*
* Web enabled FFT VU meter for a matrix, ESP32 and INMP441 digital mic.
* The matrix width MUST be either 8 or a multiple of 16 but the height can
* be any value. E.g. 8x8, 16x16, 8x10, 32x9 etc.
*
* We are using the LEDMatrx library for easy setup of a matrix with various
* wiring options. Options are:
*HORIZONTAL_ZIGZAG_MATRIX
*HORIZONTAL_MATRIX
*VERTICAL_ZIGZAG_MATRIX
*VERTICAL_MATRIX
* If your matrix has the first pixel somewhere other than the bottom left
* (default) then you can reverse the X or Y axis by writing -M_WIDTH and /
* or -M_HEIGHT in the cLEDMatrix initialisation.
*
* REQUIRED LIBRARIES
* FastLED Arduino libraries manager
* ArduinoFFT Arduino libraries manager
* EEPROM Built in
* WiFi Built in
* AsyncTCP https://github.com/me-no-dev/ESPAsyncWebServer
* ESPAsyncWebServerhttps://github.com/me-no-dev/AsyncTCP
* LEDMatrix https://github.com/AaronLiddiment/LEDMatrix
* LEDText https://github.com/AaronLiddiment/LEDText
*
* WIRING
* LED data D2 via 470R resistor
* GND GND
* Vin 5V
*
* INMP441
* VDD 3V3
* GND GND
* L/R GND
* WS D15
* SCK D14
* SD D32
*
* REFERENCES
* Main code Scott Marley https://www.youtube.com/c/ScottMarley
* Web server Random Nerd Tutorials https://randomnerdtutorials.com/esp32-web-server-slider-pwm/
* and https://randomnerdtutorials.com/esp32-websocket-server-arduino/
* Audio and micAndrew Tuline et al https://github.com/atuline/WLED
*/
#include "audio_reactive.h"
#include <FastLED.h>
#include <LEDMatrix.h>
#include <LEDText.h>
#include <FontMatrise.h>
#include <EEPROM.h>
#define EEPROM_SIZE 5
#define LED_PIN 2
#define M_WIDTH 16
#define M_HEIGHT 16
#define NUM_LEDS (M_WIDTH * M_HEIGHT)
#define EEPROM_BRIGHTNESS 0
#define EEPROM_GAIN 1
#define EEPROM_SQUELCH 2
#define EEPROM_PATTERN 3
#define EEPROM_DISPLAY_TIME 4
uint8_t numBands;
uint8_t barWidth;
uint8_t pattern;
uint8_t brightness;
uint16_t displayTime;
bool autoChangePatterns = false;
#include "web_server.h"
cLEDMatrix<M_WIDTH, M_HEIGHT, HORIZONTAL_ZIGZAG_MATRIX> leds;
cLEDText ScrollingMsg;
uint8_t peak[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
uint8_t prevFFTValue[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
uint8_t barHeights[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
// Colors and palettes
DEFINE_GRADIENT_PALETTE( purple_gp ) {
0, 0, 212, 255, //blue
255, 179, 0, 255 }; //purple
DEFINE_GRADIENT_PALETTE( outrun_gp ) {
0, 141, 0, 100, //purple
127, 255, 192, 0, //yellow
255, 0, 5, 255 };//blue
DEFINE_GRADIENT_PALETTE( greenblue_gp ) {
0, 0, 255,60, //green
64, 0, 236, 255, //cyan
128, 0, 5, 255, //blue
192, 0, 236, 255, //cyan
255, 0, 255,60 }; //green
DEFINE_GRADIENT_PALETTE( redyellow_gp ) {
0, 200, 200,200, //white
64, 255, 218, 0, //yellow
128, 231, 0, 0, //red
192, 255, 218, 0, //yellow
255, 200, 200,200 }; //white
CRGBPalette16 purplePal = purple_gp;
CRGBPalette16 outrunPal = outrun_gp;
CRGBPalette16 greenbluePal = greenblue_gp;
CRGBPalette16 heatPal = redyellow_gp;
uint8_t colorTimer = 0;
void setup() {
FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
Serial.begin(57600);
setupWebServer();
setupAudio();
if (M_WIDTH == 8) numBands = 8;
else numBands = 16;
barWidth = M_WIDTH / numBands;
EEPROM.begin(EEPROM_SIZE);
// It should not normally be possible to set the gain to 255
// If this has happened, the EEPROM has probably never been written to
// (new board?) so reset the values to something sane.
if (EEPROM.read(EEPROM_GAIN) == 255) {
EEPROM.write(EEPROM_BRIGHTNESS, 50);
EEPROM.write(EEPROM_GAIN, 0);
EEPROM.write(EEPROM_SQUELCH, 0);
EEPROM.write(EEPROM_PATTERN, 0);
EEPROM.write(EEPROM_DISPLAY_TIME, 10);
EEPROM.commit();
}
// Read saved values from EEPROM
FastLED.setBrightness( EEPROM.read(EEPROM_BRIGHTNESS));
brightness = FastLED.getBrightness();
gain = EEPROM.read(EEPROM_GAIN);
squelch = EEPROM.read(EEPROM_SQUELCH);
pattern = EEPROM.read(EEPROM_PATTERN);
displayTime = EEPROM.read(EEPROM_DISPLAY_TIME);
if (WiFi.status() == WL_CONNECTED) showIP();
}
void loop() {
if (pattern != 5) FastLED.clear();
uint8_t divisor = 1; // If 8 bands, we need to divide things by 2
if (numBands == 8) divisor = 2; // and average each pair of bands together
for (int i = 0; i < 16; i += divisor) {
uint8_t fftValue;
if (numBands == 8) fftValue = (fftResult + fftResult) / 2; // Average every two bands if numBands = 8
else fftValue = fftResult;
fftValue = ((prevFFTValue * 3) + fftValue) / 4; // Dirty rolling average between frames to reduce flicker
barHeights = fftValue / (255 / M_HEIGHT); // Scale bar height
if (barHeights > peak) // Move peak up
peak = min(M_HEIGHT, (int)barHeights);
prevFFTValue = fftValue; // Save prevFFTValue for averaging later
}
// Draw the patterns
for (int band = 0; band < numBands; band++) {
drawPatterns(band);
}
// Decay peak
EVERY_N_MILLISECONDS(60) {
for (uint8_t band = 0; band < numBands; band++)
if (peak > 0) peak -= 1;
}
EVERY_N_SECONDS(30) {
// Save values in EEPROM. Will only be commited if values have changed.
EEPROM.write(EEPROM_BRIGHTNESS, brightness);
EEPROM.write(EEPROM_GAIN, gain);
EEPROM.write(EEPROM_SQUELCH, squelch);
EEPROM.write(EEPROM_PATTERN, pattern);
EEPROM.write(EEPROM_DISPLAY_TIME, displayTime);
EEPROM.commit();
}
EVERY_N_SECONDS_I(timingObj, displayTime) {
timingObj.setPeriod(displayTime);
if (autoChangePatterns) pattern = (pattern + 1) % 6;
}
FastLED.setBrightness(brightness);
FastLED.show();
ws.cleanupClients();
}
void drawPatterns(uint8_t band) {
uint8_t barHeight = barHeights;
// Draw bars
switch (pattern) {
case 0:
rainbowBars(band, barHeight);
break;
case 1:
// No bars on this one
break;
case 2:
purpleBars(band, barHeight);
break;
case 3:
centerBars(band, barHeight);
break;
case 4:
changingBars(band, barHeight);
EVERY_N_MILLISECONDS(10) { colorTimer++; }
break;
case 5:
createWaterfall(band);
EVERY_N_MILLISECONDS(30) { moveWaterfall(); }
break;
}
// Draw peaks
switch (pattern) {
case 0:
whitePeak(band);
break;
case 1:
outrunPeak(band);
break;
case 2:
whitePeak(band);
break;
case 3:
// No peaks
break;
case 4:
// No peaks
break;
case 5:
// No peaks
break;
}
}
void showIP(){
char strIP = " ";
IPAddress ip = WiFi.localIP();
ip.toString().toCharArray(strIP, 16);
Serial.println(strIP);
ScrollingMsg.SetFont(MatriseFontData);
ScrollingMsg.Init(&leds, leds.Width(), ScrollingMsg.FontHeight() + 1, 0, 0);
ScrollingMsg.SetText((unsigned char *)strIP, sizeof(strIP) - 1);
ScrollingMsg.SetTextColrOptions(COLR_RGB | COLR_SINGLE, 0xff, 0xff, 0xff);
ScrollingMsg.SetScrollDirection(SCROLL_LEFT);
ScrollingMsg.SetFrameRate(160 / M_WIDTH); // Faster for larger matrices
while(ScrollingMsg.UpdateText() == 0) {
FastLED.show();
}
}
//////////// Patterns ////////////
void rainbowBars(uint8_t band, uint8_t barHeight) {
int xStart = barWidth * band;
for (int x = xStart; x < xStart + barWidth; x++) {
for (int y = 0; y <= barHeight; y++) {
leds(x,y) = CHSV((x / barWidth) * (255 / numBands), 255, 255);
}
}
}
void purpleBars(int band, int barHeight) {
int xStart = barWidth * band;
for (int x = xStart; x < xStart + barWidth; x++) {
for (int y = 0; y < barHeight; y++) {
leds(x,y) = ColorFromPalette(purplePal, y * (255 / barHeight));
}
}
}
void changingBars(int band, int barHeight) {
int xStart = barWidth * band;
for (int x = xStart; x < xStart + barWidth; x++) {
for (int y = 0; y < barHeight; y++) {
leds(x,y) = CHSV(y * (255 / M_HEIGHT) + colorTimer, 255, 255);
}
}
}
void centerBars(int band, int barHeight) {
int xStart = barWidth * band;
for (int x = xStart; x < xStart + barWidth; x++) {
if (barHeight % 2 == 0) barHeight--;
int yStart = ((M_HEIGHT - barHeight) / 2 );
for (int y = yStart; y <= (yStart + barHeight); y++) {
int colorIndex = constrain((y - yStart) * (255 / barHeight), 0, 255);
leds(x,y) = ColorFromPalette(heatPal, colorIndex);
}
}
}
void whitePeak(int band) {
int xStart = barWidth * band;
int peakHeight = peak;
for (int x = xStart; x < xStart + barWidth; x++) {
leds(x,peakHeight) = CRGB::White;
}
}
void outrunPeak(int band) {
int xStart = barWidth * band;
int peakHeight = peak;
for (int x = xStart; x < xStart + barWidth; x++) {
leds(x,peakHeight) = ColorFromPalette(outrunPal, peakHeight * (255 / M_HEIGHT));
}
}
void createWaterfall(int band) {
int xStart = barWidth * band;
// Draw bottom line
for (int x = xStart; x < xStart + barWidth; x++) {
leds(x,0) = CHSV(constrain(map(fftResult,0,254,160,0),0,160), 255, 255);
}
}
void moveWaterfall() {
// Move screen up starting at 2nd row from top
for (int y = M_HEIGHT - 2; y >= 0; y--) {
for (int x = 0; x < M_WIDTH; x++) {
leds(x,y+1) = leds(x,y);
}
}
}
【Arduino 动手做】ESP32 带有 INMP441 的 WS2812B 矩阵
【Arduino 动手做】可 3D 打印的 ESP32 供电 VU 显示屏,带有 INMP441 数字麦克风和 WS2812B 矩阵项目链接:https://github.com/s-marley/ESP32-INMP441-Matrix-VU
项目作者:S-马利
项目视频 :https://www.youtube.com/watch?v=9PEjvFkdpIE&t=14s
项目代码:https://github.com/s-marley/ESP32-INMP441-Matrix-VU/tree/main/INMP441Matrix
3D 文件:https://github.com/s-marley/ESP32-INMP441-Matrix-VU/tree/main/3D%20Models
WLED Sound Reactive:https://github.com/atuline
页:
[1]