kopia lustrzana https://github.com/s-marley/ESP32_FFT_VU
commit
9645716276
|
@ -1,7 +1,8 @@
|
|||
// (Heavily) adapted from https://github.com/G6EJD/ESP32-8266-Audio-Spectrum-Display/blob/master/ESP32_Spectrum_Display_02.ino
|
||||
// Adjusted to allow brightness changes on press+hold, Auto-cycle for 3 button presses within 2 seconds
|
||||
// Edited to add Neomatrix support for easier compatibility with different layouts.
|
||||
|
||||
#include <FastLED.h>
|
||||
#include <FastLED_NeoMatrix.h>
|
||||
#include <arduinoFFT.h>
|
||||
#include <EasyButton.h>
|
||||
|
||||
|
@ -68,27 +69,11 @@ CRGBPalette16 greenbluePal = greenblue_gp;
|
|||
CRGBPalette16 heatPal = redyellow_gp;
|
||||
uint8_t colorTimer = 0;
|
||||
|
||||
// XY code for serpentine matrix with input in top left
|
||||
uint16_t XY( uint8_t x, uint8_t y) {
|
||||
uint16_t i;
|
||||
|
||||
y = kMatrixHeight - 1 - y; // Adjust y coordinate so (0,0) is bottom left
|
||||
|
||||
if(SERPENTINE) {
|
||||
if( y & 0x01) {
|
||||
// Odd rows run backwards
|
||||
uint8_t reverseX = (kMatrixWidth - 1) - x;
|
||||
i = (y * kMatrixWidth) + reverseX;
|
||||
} else {
|
||||
// Even rows run forwards
|
||||
i = (y * kMatrixWidth) + x;
|
||||
}
|
||||
}
|
||||
else {
|
||||
i = (y * kMatrixWidth) + x;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
// FastLED_NeoMaxtrix - see https://github.com/marcmerlin/FastLED_NeoMatrix for Tiled Matrixes, Zig-Zag and so forth
|
||||
FastLED_NeoMatrix *matrix = new FastLED_NeoMatrix(leds, kMatrixWidth, kMatrixHeight,
|
||||
NEO_MATRIX_TOP + NEO_MATRIX_LEFT +
|
||||
NEO_MATRIX_ROWS + NEO_MATRIX_ZIGZAG +
|
||||
NEO_TILE_TOP + NEO_TILE_LEFT + NEO_TILE_ROWS);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
@ -138,7 +123,7 @@ void loop() {
|
|||
for (int i = 0; i<NUM_BANDS; i++){
|
||||
bandValues[i] = 0;
|
||||
}
|
||||
|
||||
|
||||
// Sample the audio pin
|
||||
for (int i = 0; i < SAMPLES; i++) {
|
||||
newTime = micros();
|
||||
|
@ -156,7 +141,7 @@ void loop() {
|
|||
// Analyse FFT results
|
||||
for (int i = 2; i < (SAMPLES/2); i++){ // Don't use sample 0 and only first SAMPLES/2 are usable. Each array element represents a frequency bin and its value the amplitude.
|
||||
if (vReal[i] > NOISE) { // Add a crude noise filter
|
||||
|
||||
|
||||
/*8 bands, 12kHz top band
|
||||
if (i<=3 ) bandValues[0] += (int)vReal[i];
|
||||
if (i>3 && i<=6 ) bandValues[1] += (int)vReal[i];
|
||||
|
@ -189,7 +174,7 @@ void loop() {
|
|||
|
||||
// Process the FFT data into bar heights
|
||||
for (byte band = 0; band < NUM_BANDS; band++) {
|
||||
|
||||
|
||||
// Scale the bars for the display
|
||||
int barHeight = bandValues[band] / AMPLITUDE;
|
||||
if (barHeight > TOP) barHeight = TOP;
|
||||
|
@ -201,7 +186,7 @@ void loop() {
|
|||
if (barHeight > peak[band]) {
|
||||
peak[band] = min(TOP, barHeight);
|
||||
}
|
||||
|
||||
|
||||
// Draw bars
|
||||
switch (buttonPushCounter) {
|
||||
case 0:
|
||||
|
@ -249,10 +234,10 @@ void loop() {
|
|||
// Save oldBarHeights for averaging later
|
||||
oldBarHeights[band] = barHeight;
|
||||
}
|
||||
|
||||
|
||||
// Decay peak
|
||||
EVERY_N_MILLISECONDS(60) {
|
||||
for (byte band = 0; band < NUM_BANDS; band++)
|
||||
for (byte band = 0; band < NUM_BANDS; band++)
|
||||
if (peak[band] > 0) peak[band] -= 1;
|
||||
colorTimer++;
|
||||
}
|
||||
|
@ -265,7 +250,7 @@ void loop() {
|
|||
EVERY_N_SECONDS(10) {
|
||||
if (autoChangePatterns) buttonPushCounter = (buttonPushCounter + 1) % 6;
|
||||
}
|
||||
|
||||
|
||||
FastLED.show();
|
||||
}
|
||||
|
||||
|
@ -274,8 +259,8 @@ void loop() {
|
|||
void rainbowBars(int band, int barHeight) {
|
||||
int xStart = BAR_WIDTH * band;
|
||||
for (int x = xStart; x < xStart + BAR_WIDTH; x++) {
|
||||
for (int y = 0; y < barHeight; y++) {
|
||||
leds[XY(x,y)] = CHSV((x / BAR_WIDTH) * (255 / NUM_BANDS), 255, 255);
|
||||
for (int y = TOP; y >= TOP - barHeight; y--) {
|
||||
matrix->drawPixel(x, y, CHSV((x / BAR_WIDTH) * (255 / NUM_BANDS), 255, 255));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -283,8 +268,8 @@ void rainbowBars(int band, int barHeight) {
|
|||
void purpleBars(int band, int barHeight) {
|
||||
int xStart = BAR_WIDTH * band;
|
||||
for (int x = xStart; x < xStart + BAR_WIDTH; x++) {
|
||||
for (int y = 0; y < barHeight; y++) {
|
||||
leds[XY(x,y)] = ColorFromPalette(purplePal, y * (255 / barHeight));
|
||||
for (int y = TOP; y >= TOP - barHeight; y--) {
|
||||
matrix->drawPixel(x, y, ColorFromPalette(purplePal, y * (255 / (barHeight + 1))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -292,8 +277,8 @@ void purpleBars(int band, int barHeight) {
|
|||
void changingBars(int band, int barHeight) {
|
||||
int xStart = BAR_WIDTH * band;
|
||||
for (int x = xStart; x < xStart + BAR_WIDTH; x++) {
|
||||
for (int y = 0; y < barHeight; y++) {
|
||||
leds[XY(x,y)] = CHSV(y * (255 / kMatrixHeight) + colorTimer, 255, 255);
|
||||
for (int y = TOP; y >= TOP - barHeight; y--) {
|
||||
matrix->drawPixel(x, y, CHSV(y * (255 / kMatrixHeight) + colorTimer, 255, 255));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -305,25 +290,24 @@ void centerBars(int band, int barHeight) {
|
|||
int yStart = ((kMatrixHeight - barHeight) / 2 );
|
||||
for (int y = yStart; y <= (yStart + barHeight); y++) {
|
||||
int colorIndex = constrain((y - yStart) * (255 / barHeight), 0, 255);
|
||||
leds[XY(x,y)] = ColorFromPalette(heatPal, colorIndex);
|
||||
matrix->drawPixel(x, y, ColorFromPalette(heatPal, colorIndex));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void whitePeak(int band) {
|
||||
int xStart = BAR_WIDTH * band;
|
||||
int peakHeight = peak[band];
|
||||
int peakHeight = TOP - peak[band] - 1;
|
||||
for (int x = xStart; x < xStart + BAR_WIDTH; x++) {
|
||||
leds[XY(x,peakHeight)] = CRGB::White;
|
||||
matrix->drawPixel(x, peakHeight, CHSV(0,0,255));
|
||||
}
|
||||
}
|
||||
|
||||
void outrunPeak(int band) {
|
||||
int xStart = BAR_WIDTH * band;
|
||||
int peakHeight = peak[band];
|
||||
int peakHeight = TOP - peak[band] - 1;
|
||||
for (int x = xStart; x < xStart + BAR_WIDTH; x++) {
|
||||
//leds[XY(x,peakHeight)] = CHSV(peakHeight * (255 / kMatrixHeight), 255, 255);
|
||||
leds[XY(x,peakHeight)] = ColorFromPalette(outrunPal, peakHeight * (255 / kMatrixHeight));
|
||||
matrix->drawPixel(x, peakHeight, ColorFromPalette(outrunPal, peakHeight * (255 / kMatrixHeight)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -333,14 +317,16 @@ void waterfall(int band) {
|
|||
|
||||
// Draw bottom line
|
||||
for (int x = xStart; x < xStart + BAR_WIDTH; x++) {
|
||||
leds[XY(x,0)] = CHSV(constrain(map(bandValues[band],0,highestBandValue,160,0),0,160), 255, 255);
|
||||
matrix->drawPixel(x, 0, CHSV(constrain(map(bandValues[band],0,highestBandValue,160,0),0,160), 255, 255));
|
||||
}
|
||||
|
||||
// Move screen up starting at 2nd row from top
|
||||
if (band == NUM_BANDS - 1){
|
||||
for (int y = kMatrixHeight - 2; y >= 0; y--) {
|
||||
for (int x = 0; x < kMatrixWidth; x++) {
|
||||
leds[XY(x,y+1)] = leds[XY(x,y)];
|
||||
int pixelIndexY = matrix->XY(x, y + 1);
|
||||
int pixelIndex = matrix->XY(x, y);
|
||||
leds[pixelIndexY] = leds[pixelIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ A spectrum analyzer VU meter running a 40kHz FFT on an ESP32 and outputting to a
|
|||
If you're inerested in running this using Neomatrix for easier adjustment to different matrix setups, [VonHirsch](https://github.com/VonHirsch/ESP32_FFT_VU/tree/FastLED_NeoMatrix) has a fork that you might be interested in.
|
||||
|
||||
## Demo
|
||||
If you are planning on using this code, it is advisable to watch the YouTube video below explaining how it works.
|
||||
If you are planning on using this code, it is advisable to watch the YouTube video below explaining how it works. Please note, the code has changed to use FastLED Neomatrix since the video was produced thanks to [VonHirsch](https://github.com/VonHirsch/). See 'Installation and code usage' below.
|
||||
|
||||
[![Youtube video of VU meter in action](http://img.youtube.com/vi/Mgh2WblO5_c/0.jpg)](https://www.youtube.com/watch?v=Mgh2WblO5_c)
|
||||
|
||||
|
@ -24,8 +24,9 @@ This is much simpler than the line in method, but you will be limited to the fre
|
|||
|
||||
## Installation and code usage
|
||||
1. Download this repository and open ESP32_FFT_VU.ino.
|
||||
2. You will need the FastLED and EasyButton libraries from the Arduino library manager. Youw will also need the arduinoFFT library. At the time of writing, the library manager version arduinoFFT has a bug which prevents `DCRemoval()` from working, so download it from the [GitHub repository](https://github.com/kosme/arduinoFFT) and install it from a zip file.
|
||||
3. Watch the video to see how to use it, you will need to customise it to your matrix and your needs.
|
||||
2. You will need the FastLED Neomatrix and EasyButton libraries from the Arduino library manager. Youw will also need the arduinoFFT library. At the time of writing, the library manager version arduinoFFT has a bug which prevents `DCRemoval()` from working, so download it from the [GitHub repository](https://github.com/kosme/arduinoFFT) and install it from a zip file.
|
||||
3. Watch the video to see how to use it.
|
||||
4. To customsise it to your own matrix layout, read about Neomatrix layouts at [Adafruit](https://learn.adafruit.com/adafruit-neopixel-uberguide/neomatrix-library#layouts-2894555-5).
|
||||
|
||||
## Controls
|
||||
The matrix is controlled from a single button. The functions are:
|
||||
|
|
Ładowanie…
Reference in New Issue